htmlspecialchars関数を簡単に扱えるようにする
2008年01月12日 プログラミングTIPS
特殊文字を HTML エンティティに変換してくれるhtmlspecialchars関数。
PHPでは基本中の基本である関数でありながら、名前の長さやオプションの設定などが面倒で困ったものです。「htmlspecialchars」は覚えられても、オプションの「ENT_QUOTES」まで覚えるのはなかなか大変だったりします。でも、ここで手を抜くと簡単に脆弱なアプリケーションができあがってしまう危険性があります。特にユーザーからの入力には、手軽にがっちり入力保険をかけておくべきです。
そんなわけで、htmlspecialcharsを簡単に扱えるようにする方法を考えてみました。
お知らせ:PHP5.4にて、htmlspecialchars()関数に互換性の問題が出てきましたので、当ページでも第三引数に文字コードを指定するコードに変更しました。以下、第三引数の"UTF-8"の部分は、利用中の文字コードに合わせて変更してください。(例:Shift_JIS、EUC-JP、ISO-8859-1など)
PHPでは基本中の基本である関数でありながら、名前の長さやオプションの設定などが面倒で困ったものです。「htmlspecialchars」は覚えられても、オプションの「ENT_QUOTES」まで覚えるのはなかなか大変だったりします。でも、ここで手を抜くと簡単に脆弱なアプリケーションができあがってしまう危険性があります。特にユーザーからの入力には、手軽にがっちり入力保険をかけておくべきです。
そんなわけで、htmlspecialcharsを簡単に扱えるようにする方法を考えてみました。
お知らせ:PHP5.4にて、htmlspecialchars()関数に互換性の問題が出てきましたので、当ページでも第三引数に文字コードを指定するコードに変更しました。以下、第三引数の"UTF-8"の部分は、利用中の文字コードに合わせて変更してください。(例:Shift_JIS、EUC-JP、ISO-8859-1など)
関数名を短縮し、オプションも指定する
htmlspecialchars関数が使いにくいのは、名前が長いのとオプションの指定が面倒だからです。よって、次のように置き換えてしまえば、簡単に使えます。「htmlspecialchars」関数を「h」という関数前で置き換え、オプションの「ENT_QUOTES」(シングルクオートとダブルクオートを共に変換するオプション)と文字コードを直接指定しています。文字コードは環境に合わせて変更してください。function h($str){ return htmlspecialchars($str,ENT_QUOTES,"UTF-8"); }
利用する際は、次のように入力が短くなり、簡単に扱えるようになります。
//今まで htmlspecialchars($str,ENT_QUOTES,"UTF-8"); ↓↓↓ //これから
h($str);
配列ごと変換できるようにする
「h($str);」で簡単に変換できるようにはなりましたが、変換対象が多い配列などでは、毎回の変換が大変です。そこで、配列でも同じ方法で変換できるように書き換えます。「is_array」関数で、引数のデータが配列かどうかを調べ、配列の場合は「array_map」関数で配列全てを変換しています。function h($str){ if(is_array($str)){ return array_map("h",$str); }else{ return htmlspecialchars($str,ENT_QUOTES,"UTF-8"); } }
入力と出力例は、次のようになります。
//入力データ $str1 = array("one<br>", "<b>two</b>", '"three"', "'four"); $str2 = "<br>"; print_r(h($str1)); print_r(h($str2));
//出力データ Array ( [0] => one<br> [1] => <b>two</b> [2] => "three" [3] => 'four ) <br>
これで、通常の変数でも配列でも、簡単に変換できるようになりました。
追記:
PHP5.4にて、htmlspecialchars()関数の仕様が変更されました。第三引数の文字エンコーディングの取り扱い方が変わっています。文字エンコーディングのオプションを正しく設定していない場合、出力が空になります。したがって、短縮する関数にも第三引数の指定が必須となります。その際、文字コードをいくつも使い分けているようであれば、h()関数一つではなく、h_utf8()関数やh_eucjp()関数など、それぞれ文字コード別に関数を作ってしまうのも一つの手かもしれません。