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

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をつけたりするなど、読んで字のごとくだ。見逃しやすい関数に思えるのでメモしておくことにした。

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

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
}

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

eval関数

2007/02/12 | マイPHPメモ

だいたいどんな言語でも存在するeval関数についての話題。

もともとPHPはシフトJISはサポートしていない。プログラムを設置する際に、その発注先はプログラムの知識がないことが多いし、しかもそういうクライアントに限って「あとで自分たちでも改変できるように」なんて無茶なリクエストをすることが多々ある。そういうクライアントはたいていの場合文字コードに関しての知識はないに等しい。
そんなときにeval関数は便利だ。設定ファイルをシフトJISで書いてしまい、それを読み込む際に文字コードを変換して、さらにevalしてPHP化してしまうわけだ。例えば・・・。

設定ファイルを以下のように記述する(ファイル名「setting.txt」)。
define(‘MIDASHI1′,’見出し1′);

ここで設定ファイルには<?phpといったお決まりの文句を書かないことがキーポイントだ。でもって、このファイルは誰でも修正できるようシフトJISで書いておく。
このファイルをPHPプログラムから以下のようにして読み込めばOKだ。

<?php
$setting=file_get_contents(‘setting.txt’);
$setting=mb_convert_encoding($setting,’EUC-JP’,’SJIS’);
if(@eval($setting)===false){
(PHP化失敗)
}else{
(処理を書く)
}
?>

ここで@eval($setting)===falseと「===」でくくるのがミソ。元のファイルに構文エラーがなかった場合に、元のファイル中にreturn文がなかった場合、@eval($setting)はNULLを返してしまうからだ。
if(!@eval($setting){〜}なんて記述をしてしまうと、永久に???の世界の中にとどまることになってしまうので注意が必要だ。

諸刃の刃ではあるのだが、eval関数というのは便利だ。

PHPで日本語メールを送信する際のメモ

2006/07/03 | マイPHPメモ

PHPで日本語メールを送信するときの注意事項をいくつか(mb_send_mailで送ることを前提)。

○以下の2行を必ず指定(文字コードは必要応じて適宜)。
<?php
mb_language(‘japanese’);
mb_internal_encoding(‘EUC-JP’);
?>

○76文字ルール
第4引数を指定する際に、一行76文字以内となるよう調整する必要有り。

○To、Cc、Bccのメールの書式は「名前 <user@example.com>」と記述。

○本文は基本的に自動変換してくれるはず。それ以外のところで文字化けが発生する場合はmb_encode_mimeheaderを使ってエンコードする(必要に応じて適宜やる必要がある)。

「必要に応じて」と書いたのはうまくいったりうまくいかなかったりする場合があるからで、全ての場合を考える暇もないから。トラブルが起こったときに対応するほうが結局コストが安くつく。


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