文字列のエスケープ

2008/04/12 | PHPの基本

例えば掲示板プログラムを作った場合、入力された文字はそのままデータベースやテキストファイルで保存して、出力するときに<や>などを変換して表示するのはよくあることだ。これには通常htmlspecialchars関数を使用する。しかしこの関数、実は奥深い。
まずhtmlspecialcharsとよく似た働きをする関数にhtmlentitiesという関数がある。両者の違いは何かというと、実際に引数で与えられた文字列を変換する際に、変換する文字列の種類(というか変換する文字数)が違うのだ。基本的にhtmlspecialcharsでは「>」「<」「"」「&」だけなのだが(HTMLで使用する際に支障が出そうな文字列だけを変換)、htmlentitiesでは、&と;で囲んだ文字に変換できるものはすべて変換するのだ。htmlspecialcharsで変換されないものは、実は結構たくさんある。両者の違いは以下の2行のスクリプトを実行すればわかるだろう(普通のウェブ開発で使用することはまずないので、一回くらいは試してみてもいい)。

print_r(get_html_translation_table(HTML_ENTITIES));
print_r(get_html_translation_table(HTML_SPECIALCHARS));

つまり変換で使用する一覧を、それぞれの関数の場合で表示させることができるのだ。本来変換可能な文字列というのは、割とたくさんあることがわかるだろう。

さてhtmlspecialcharsで通常変換する文字列が「>」「<」「"」「&」と言ったが、何か気にならないだろうか。気になった人は鋭い。「'」だ。HTMLで属性の値を囲むときは通常「"」を使うが「'」も使うことが可能だ。であれば「'」も変換できたほうがいいはずだ。

実はこの「'」は、デフォルトでは変換されないのだが、htmlspecialchars関数に第二引数を与えることによって変換することができる。ちなみに第二引数でとりうる値は以下の3つだ。

ENT_COMPAT 「'」は変換せず「"」は変換(デフォルト)
ENT_quotS 「'」も「"」は変換
ENT_NOquot 「'」も「"」も変換せず

シングルクォーテーション、ダブルクォーテーションにはいろいろあるわけだ。ちなみにhtmlentitiesでも上記と同様第二引数で指定することができる。基本的に両者は同じなのだが、日本語環境でほとんどhtmlentitiesが使われないのは、例えば半角カナが割り当てられた領域も変換をかけようという処理が入ってしまうためにもろもろ不具合がでる、というところによるのだろう。

htmlspecialcharsのような一般的な関数でも、実は奥が深かったりする。前からうすうす理解はしていたのだが、しっかり調べるとなるほど納得。やはりおくが深いのだ。

関数の呼び出し方(変数と括弧)

2008/04/02 | PHPの基本

以前、文字列操作関数substrの特別な場合として以下のような記述方法について記事を書いた。

$variable=’abcdefg';
print($valiable{3});
// 結果は「d」が表示される

変数名に{}をつけることで関数の代わりになるというお話しだった。
今回あるプログラムを読んでいて、こんな記述を見つけた。
$variable();

変数名に()って・・・今度は何?、と思って調べたらこれは以下のようなことだった。

$variable=’abcdefg';
$valiable();
// こちらはabcdefg()という関数が実行される

もちろんabcdefg()という関数が定義されていないとエラーになる。call_user_func関数の代わりに使うのだろうか。いずれにしてもプログラムの可読性が悪くなるような気がしないではない。

多次元配列をソートする

2007/12/10 | PHPの基本

とある案件で、配列に格納されたデータをソートする処理が必要になった。
今までは、基本的にデータの保存にはデータベースを使用していたので、配列としてデータを取り扱う以前にデータのソートは完了しているのが常だった。しかし今回データベースを使用せず、CSV形式で与えられていたので、配列に格納されたデータをソートする必要が出てきたわけだ。
実はこの処理、それほど難しいわけではなく、PHPで標準装備の関数で対応できる。それがarray_multisort関数だ。ただコマンド一発!というわけではなく、事前準備が必要となる。処理内容は以下の通り。

foreach ($data as $key => $row) {
$volume[$key] = $row[‘volume’];
$edition[$key] = $row[‘edition’];
}
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);

条件としてデータ「$data」が多次元配列で、その各行でいくつかのデータが指定され、かつ、それらのデータのうち「volume」「edition」というキーで与えられた値を元にソートするものとする。

最初のforeach文で、各行の「volume」「edition」のキーで指定された値をあらかじめ全て取り出して、変数に格納しておく必要がある。これを使い、array_multisort関数にデータ、ソート対象を引き渡す。関数が実行されると$dataがソートされている、というわけだ。

この関数、引数の与え方が他の関数とずいぶん違うので、使用する際は注意が必要になる。上記の例では、


第1引数:あらかじめ抽出したソート対象の配列
第2引数:ソート方法(昇順、降順)
:(上記2つの繰り返し)
最後の引数:データ

となっている。これは時としてこんな具合にもなる


第1引数:あらかじめ抽出したソート対象の配列
第2引数:ソート方法(昇順、降順)
第3引数:ソートのフラグ(文字列として、数値として等)
:(上記3つの繰り返し)
最後の引数:データ

慣れるまでは注意が必要な関数だ。

ヒアドキュメント内で配列変数の展開

2007/11/20 | PHPの基本

ヒアドキュメントは便利な機能だ。複数行に及ぶ文字列をクオーテーション("や’)で囲まなくても、変数に格納したり、出力に使用したりすることができる。それにヒアドキュメント内で変数を使用すれば、ちゃんと展開してさえもくれる。こんな感じ。

$str=’テクメモ';
$doc=<<<__TESTDOC
これはテストです。
$str
__TESTDOC

上記で$docには「これはテストです。(改行)テクメモ」というテキストが格納される。
もちろん$strのような単なる文字列が格納された変数だけではなく、配列の要素も代入することが可能なのだが、これには一工夫必要になる。

$strArray=array(‘mother’=>’ママ’,’father’=>’パパ’);
$doc=<<<__TESTDOC
{$strArray[‘father’]}
{$strArray[‘mother’]}
__TESTDOC

おわかりだろうか。通常は配列の各要素を指定する場合は「変数名[キー]」の形で指定するのだが、ヒアドキュメント内ではさらにそれらを{}でくくってやる必要がある。

普段あんまりヒアドキュメントを使うことがないので知らなかった。

n番目の文字1つを取り出す

2007/09/26 | PHPの基本

phpでn番目の文字を取り出したいとき、ついさっきまでは以下のように記述するしかないと思っていた。

$str=’abcdefgh';
$char=substr($str,3,1);

こうすると$charには「d」が格納される(phpでは最初は1ではなく0から始まることに注意)。しかしもっと簡単な書き方があることを知った。

$str=’abcdefgh';
$char=$str{3};

なんと、こんな書き方でも同様の結果を得ることが出来る。マルチバイト系ではうまく動かないような気もするが(未検証)、これは簡単だ。多分関数を呼ばない分だけオーバーヘッドも少なく、処理速度も速いだろう。
少しだけ賢くなった。


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