文字コードUTF-8で、BOMの有無による問題

Xoopsのモジュールを書いていて、すごく悩ましい問題に出くわした。
テンプレートを2つ(それぞれ仮にAとBと呼ぶことにする)用意したのだが、同じようなタグしか記述していないのに、どうしても片方で余白ができてしまう。原因を突き止めるためにテンプレートの中身を最低限の内容にしてみた。

テンプレートAの中身
<div>A</div>

テンプレートBの中身
<div>B</div>

しかしこれでも片方で余白が出来てしまう。これはスタイルシートとかタグレベルの問題ではないことは明白だ。では何がそうさせるのか。
答えは「UTFのBOM」でした。

最近は文字コードとしてUTF-8を使用するようにしている。テキストエディタとしてEmEditorを愛用しているのだが、UTF-8でもBOMの有無を設定できるようになっている。
BOMとはUTF-16で必要となる「ビット列の並び」を示す符号のようなものだ(検索したらそう書いてあった)。本来UTF-8では必要ないはずなのだが、UTFで書かれているということを示すためだけにBOMがつけられるとのことだった。

前述の問題は片方のテンプレートがBOM付きで保存されていたことが問題で、BOMをとって保存すると余白なく表示されることを確認できた。
いずれにしても文字コードは、問題を引き起こす原因の一つであることは間違いないようだ。

マルチバイト関数には文字コード指定

2007/08/15 | マイPHPメモ

今まで使ってたプログラムを別の環境に移設したら正しく動作しなくなった、というのはよくある話だ。今回マルチバイト文字を切ったり張ったりするプログラムを別の場所に移植しようとしたら全然動かなかった。

「正しく(予期したとおりに)動かない」というのには何らかの理由があるはずだ。

PHPには日本語(マルチバイト文字)を扱うための関数群(マルチバイト関数)がある。今回はこの関数が、期待する動作をしてくれなかったために発生してしまったようだ。「マルチバイト関数が期待通りの動作をしない」という場合、大抵は正しく文字コードを認識していないことに起因する。今回もそのとおり、文字コードを正しく認識していなかったようだ。

では、正しく認識させる方法。これには二つある(と思う)。
(1) 設定でプログラムの文字コードを指定しておく。
 要は「スクリプトのエンコーディングが何なのか」ということをphp.ini、.htaccessなどで指定しておくことだ。
(2) マルチバイト関数の引数で文字コードを渡す。
 mb_で始まる関数は大抵その引数で、文字コードを指定して渡すことが出来るので、正しい文字コードを指定しておく。

この2点。
ちょっと頭の片隅に入れておく。

extract — 配列から変数を生成

2007/08/14 | マイPHPメモ

プログラムを書くのになるべく注意していることがいくつかある。第一は可読性だ。あとで見直したときに「何書いたんだっけ」ということになるとメンテナンスできない。第二に「短いプログラム」を心がけている。長いプログラムは正直言って、後で読む気がなくなるからだ。
プログラムを短縮するのに便利な関数を一つ。「extract」を便利に使っている。この関数は連想配列から、キーを変数名として配列を複数の数の変数に展開してくれる関数だ。例えばこんな風に使う。

$myArray=array(‘id’=>1,’name’=>’php’);
extract($myArray);

これで$id=1、$name=’php’という二つの変数が出来上がる。ただしこれだと既に$idとか$nameといった変数があった場合に上書きされてしまうが、第二引数、第三引数を指定することで挙動にバリエーションを持たせられる。
例えば以下のように指定する。

$id=10;
$myArray=array(‘id’=>1,’name’=>’php’);
extract($myArray,EXTR_PREFIX_SAME,’new’);

このように記述すると$id=10、$name=’php’、$new_id=1という具合に、上書きしないよう衝突してしまった変数名にのみprefixをつけてくれる。挙動のオプションはいろいろ選べる。

EXTR_OVERWRITE
EXTR_SKIP
EXTR_PREFIX_SAME
EXTR_PREFIX_ALL
EXTR_PREFIX_INVALID
EXTR_IF_EXISTS
EXTR_PREFIX_IF_EXISTS
EXTR_REFS

上書きしたり、常にprefixをつけたりするなど、読んで字のごとくだ。見逃しやすい関数に思えるのでメモしておくことにした。

XoopsでRSSを配信

2007/08/12 | XOOPS

XoopsでRSSを配信したい、というリクエストをいただいた。早速検索してみるとRSSfitというモジュールが紹介されていた。URLはここ

ここで紹介されていたRSSfit1.1を使用してみた。RSS配信したいモジュール用のプラグインを作成すれば準備完了だ(あとモジュールに対するアクセス権限も)。
結論からいくといとも簡単にRSSを配信することが出来た。

ちなみにこの上記で紹介したサイトで配布されているRSSfitJ(独自に日本語対応されたモジュール)は現行のXoops(2.0.16a JP)では動作しなかった(管理画面がうまく動いてくれないので設定のしようがない)。

RSSfitの本家を見てみた。こちらではRSSfitの最新版(1.21)が配布されていた。
ちなみにこちらでも、プラグインを作ることで正しく動作しているように見えるが、管理画面中で文字化けしているようなところが見受けられたので、今回は使用しなかった。多言語パックも用意されているようだが、日本語は用意されていなかった(残念)。
日本語版、つくってもいいかもしれない。でも、本家がマルチバイト対応していないので、プログラム本体のソースを全部追わないといけないので、それはそれでちょっと大変・・・。

最近のお気に入り「コールバック関数」

2007/08/11 | マイPHPメモ

最近コールバック関数がお気に入りだ。おそらく使わなくてもいいような関数ではあるのだが、使うことでスクリプトがすっきりするからだ。

例えば、ある配列が以下のように定義されているとする。
$myArray=array(
  [0]=>array(‘a’,’b’),
  [1]=>array(‘c’,’d’),
  [2]=>array(‘e’,’f’),
  [3]=>array(‘g’,’hb’),
    :
    :
);

この配列のそれぞれの値について処理をする方法を考える。まず通常はforeachなどでループ処理を書けばよい。
foreach($myArray as $myValue){
  //処理1
}

ここに別の要素が加わるとする。例えば別の変数があり、その変数の値がtrueなら処理1を、falseなら処理2をさせるとする。プログラムを羅列するとこんな風になる。
if($flag){
  foreach($myArray as $myValue){
    //処理1
  }
}else{
  foreach($myArray as $myValue){
    //処理2
  }
}

これはいかにも冗長だ。しかしコールバック関数を使うときれいなプログラムがかける。
$funcName=($flag ? ‘proc1′:’proc2′);
array_walk($myArray,$funcName);
function proc1{
  //処理1
}
function proc2{
  //処理2
}

まぁ、どちらが美しいかというのは、人それぞれの感性によるものだからなんともいえないのだが、個人的には後者のプログラムのほうがすっきりしているように見える。array_walkという関数が難しければ、こんなふうにもかける。
$funcName=($flag ? ‘proc1′:’proc2′);
foreach($myArray as $myValue){
  call_user_func($funcName,$myValue);
}
function proc1{
  //処理1
}
function proc2{
  //処理2
}

要は関数名そのものを変数に格納し、その変数を読むことによって、希望する関数を呼び出す、ということ、になる。
あまりコールバック関数ばかり使うと、逆にプログラムが読みにくくなってしまう可能性も無きにしも非ずだが、適度に利用することで、すっきりしたプログラムが書けるようになる。
今まで使えなかった機能をつけるようになるというのは、少し楽しい。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net