配列にフィルタリングして必要な値だけ取り出す

2009/05/08 | PHPの基本

配列を処理するならたいていの場合foreachだ。ループ処理するのが簡単。でもPHPでは配列を処理するための関数がいろいろ用意されている。常識的に考えれば、それらの関数を使ったほうが早く動作するはず。

array_filterという関数を見つけた。というか前から興味を持っていた関数だ。配列をループ処理し、各値の要不要を判断して間引いてくれる関数だ。この間引き処理で、foreachを使うよりarray_filterのほうがどのくらい早くなるのか試してみた。

(1) foreachの場合
$filtered=array();
foreach($values as $value){
  if($value[‘age’]>3){
    $filtered[]=$value;
  }
}

(2) array_filterの場合
function age($value){
  if($value[‘age’]>3){
    return true;
  }else{
    return false;
  }
}
$filtered=array_filter($values,’age’);

と二つのサンプルで比べてみた。結果・・・foreachのほうが倍くらい早かった。おいおい。なんでだろ。(2)だと関数を読んでるから遅くなるのかな。

呼び出し元を取得

2009/01/26 | PHPの基本

最近は基本的にべたでプログラムを書くことはなくて、フレームワークを使ってクラスやら関数やらを書くことがほとんど。そのクラスとか関数から、さらにクラスや関数を呼び出すわけだが、呼び出された側で、呼び出し元の情報にアクセスする際、今までは引数で渡す処理にしていた。もちろんこれはこれで「必要以上の変数にはアクセスさせない」というフールプルーフ的なメリットが大きいが、その都度引数を渡す必要がある。いろいろ調べたら、PHPには呼び出し元のクラス(オブジェクト)にアクセスできる仕組みが用意されていた。

debug_backtrace関数だ。

読んで字のごとく、バックトレースしてくれるわけだ。呼び出し元クラス名やオブジェクト名、関数名やファイル名など、いろいろな情報にアクセスできる。しかし、まぁdebugとついているくらいだから、本来はデバッグ用で使用するためのものだろう。使うのには注意が必要かな。

関数emptyの引数

2009/01/16 | PHPの基本

値が空かどうかをチェックするのにempty関数をよく使っている。でも、あるとき、以下のようなエラーが出た。

Fatal error: Can’t use method return value in write context in /path/to/script

ぱっと見ただけでは意味がわからない・・・しばらく考える・・・「メソッドの戻り値は使えない」・・・。

プログラムの中では以下のように記述していた。

empty($hoge->fuga())

しかし、以下のように記述するとエラーにならない。

$value=$hoge->fuga();
empty($value); 

あ、ひょっとして・・・。

マニュアルを見たら書いてあった。「emptyの引数は関数であってはならない」そうだ。これは知らなかった。というよりも、よく今までこういう記述をしていなかったものだと思った。

mb_encode_mimeheaderの使い方

2008/12/07 | PHPの基本

PHPからメールを送信するとき、mail関数やmb_send_mail関数などを使う。このとき、Fromとして送信元を指定する場合、第4引数として「From: test@example.com」のように与えると、送信元を指定したメールを送信することができる。ただしこのままでは日本語は使えない。この引数はそのままメールのヘッダとして追加されるので、日本語は適切に変換をかけなければいけないことになっている。

ここまでは当たり前の話だが、注意しなくてはいけないのは、日本語の適切な変換をかけるための関数「mb_encode_mimeheader」の使い方だ。マニュアルを見ると以下のように書いてある。

string mb_encode_mimeheader ( string str [, string charset [, string transfer_encoding [, string linefeed]]] )

mb_encode_mimeheader() は、MIME ヘッダ エンコーディング方式によって文字列 str をエンコードします。この関数は、ASCII 表現の文字列を返します。
charset
は、str の文字セット名です。デフォルトは、現在の NLS 設定 (mbstring.language)によって決まります。
transfer_encoding
は MIME エンコーディングの 方式を指定します。“B” (Base64) または “Q” (Quoted-Printable) のどちらかでなければなりません。 デフォルトは “B” です。

第一引数はいうまでもなく変換したい文字列だ。この関数では基本的にこの第1引数だけを指定しておくのが無難。必要に応じて以降の引数を設定することもあるだろうが、第2引数の扱いには注意が必要だ。

マルチバイト関数ならたいてい使用している文字コードを引数として与えるオプションがついている(これはmbstring.internal_encodingに連動している)。しかしこのmb_encode_mimeheaderで与えるcharaset(第2引数)はその意味がまったく異なる(ようだ)。

例えばUTF-8でプログラムを記述しているからといって以下のように記述するのはNGだ。

mb_encode_mimeheader($str, ‘UTF-8′);

変換結果を出力すると以下のようになっている。

=?UTF-8?B?・・・・・・・・・・・・

本来なら「=?ISO-2022-JP?B?・・・・・・・・・・・」なはずなのに・・・。理由は省略するとして正しくは以下のように記述しておくのが無難なようだ。

mb_language(‘Japanese’);
mb_internal_encoding(‘UTF-8′);
$str=mb_encode_mimeheader($str);

1行目のmb_language関数でmb_encode_mimeheader関数に対して「日本語ルールで変換せよ」と命令していることになる。2行目で「現状文字列はUTF-8で記述されているので、UTF-8から変換すればよいものと想定して処理せよ」といった感じだろうか。だから1行目と2行目を記述しておくことだけでいいはずだ。

ちなみに引数として渡すには、以下の内容でmail関数やmb_send_mail関数の第4引数として渡せばよい。

mb_language(‘Japanese’);
mb_internal_encoding(‘UTF-8′);
$option=’From: ‘.mb_encode_mimeheader(‘名前’).'<test@example.com>';
mail($recipient,$subject,$message,$option);

文字コードで最近感じていること

2008/11/09 | PHPの基本

PHPと文字コードの問題にはいつも悩まされる。マニュアルを見ると、やはりいまだに内部エンコーディングとしてシフトJISは扱えないようだ。Zend Multibyteが有効になっていれば大丈夫、という記述を昔よく見たけど、そういえば最近はあまり見ない。でも、やっぱりシフトJISでPHPを記述するのはダメなんだろう。それでも世の中はシフトJISのPHPプログラムだらけなのだが・・・。

まぁ、自分で記述する際はプログラムはUTF-8で書くことにしている。だから制約がない場合は、基本的にプログラム、データベース、出力の全てをUTF-8で統一している。しかし出力をシフトJISにしないといけない場合がある。携帯対応とか、スキルの低いコーダー(シフトJIS以外はわからない)に対応してあげるときとか、だ。

そんなときは、管理画面のみUTF-8で通すなどといったことはやめたほうがよさそうだ。フロントエンドがシフトJISなら管理画面もシフトJISのほうが無難。でも内部エンコーディングはUTF-8。で、やるべき作業は、mb_convert_encoding。で、今更ながらこの関数はちゃんと理解して使うべきだと思っている。もちろんこの関数のみならずマルチバイト関数そのものを理解して使わないといけない。

マルチバイト関数に関する設定項目にscript_encodingやinternal_encodingがあるがまずはこの意味をしっかりと理解すべき。その上でSJISよりもsjis-win、EUC-JPよりもeucjp-win。スキルが低くてもマニュアルに目を通しておくべきだし、文字コードのことは理解していなくても後者を使うべきだろう(と思っているだけで根拠を言えるほどスキルは高くない自分がいる)。

過去の遺産はそうはなっていない。そのときは問題自体はある程度理解していたんだけれど、それでよし、としていた。どうしようか。

放置だな。


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