こんにちは!
ナビゲータのEVEです。
昨日までPHPの仕様について調べてきましたが、正直って、こんなコトするのは珍しいことです。普通は最初覚えた仕様で作っていきます。本日は、そういうことをしていると損をしてしまうという話です。
[htmlspecialchars]
htmlspecialcharsは、PHP4.0に追加された関数です。htmlspecialcharsの仕様目的は、PHPの教本などを読んでいると、クロスサイドスクリプティング対策としていますが、実は他にもあります。それは、データベースへの登録です。
現在のバージョンは不明ですが、以前のMySQLなどでは、htmlspecialcharsによりエスケープしていない文字列を登録しようとした場合、エラーになることがあります。そのため、ユーザーが入力するデータばかりではなく、実は、データベースに登録するすべてのデータはエスケープしなければなりませんでした。
[Knowlegeシステム]
以前から、勉強した知識など、Prototype EVEのKnowlegeシステムへ登録して、知識として残しているという話をしていますが、そのシステムでも、HTML画面から入力した情報を、必ず、htmlspecialcharsを使って、エスケープしています。ただ、知識として残そうとしているため、入力した情報をいろいろなタグを使用して表示したいというニーズがあります。
ただ、HTMLをブログで使用しようとした人は知っていると思いますが、HTMLタグを<textarea>から入力したデータは実はきれいに表示することができません。そのため、Knowlegeシステムでは、きれいに表示できるように、独自タグを利用して、強引にきれいに見えるように変換しています。
ただ、そこで困ったことが出てきます。タグを変換した文字列には、必ず&(アンバサンド)が入るのですが、何回か変換すると、&(アンバサンド)のampがどんどん増えていくのです。以下がその例です。
変換前→&
1回目の変換→&amp;
2回目の変換→&amp;&amp;
3回目の変換→&amp;&amp;&amp;
・
・
・
・
バグがあった場合などや、データベースの登録方法などにより、何回もhtmlspecialcharsが使用されると以上のようなことになり、&を表示したいだけなのに、全く違う文字列になってしまうということがあります。
[PHP5.0]
価格:3740円 |
ただ、今回独習PHP第4版を読んで知ったのですが、PHP5.0からhtmlspecialcharsへある引数を設定することにより、特殊文字表記を崩さずに変換できるという機能が追加されました。以下が、構文です。
htmlspecialchars(string $string, int $flags = ENT_COMPAT, ?string $encoding = null, bool $double_encode = true): string
$string (string)
エスケープしたい文字列を指定します。
$flags (int)
オプションで、エスケープ処理の方法を指定します。デフォルトは ENT_COMPAT です。ENT_QUOTES や ENT_NOQUOTES など、異なるオプションが指定できます。
$encoding (?string)
文字エンコーディングを指定します。指定しない場合、PHPのデフォルトエンコーディング(通常は UTF-8)が使用されます。null を渡すことも可能です。
$double_encode (bool)
デフォルトは true です。true の場合、既にエスケープされた文字(例えば、&)も再エスケープします。false の場合は、再度エスケープしません。
以上の$double_encodeにfalseと指定すれば問題ないところを、実は、Knowlegeシステムでは、涙ぐましい努力をしています。独習PHP第4版を読んでいるとき、この機能を知っていれば、もっと楽ができたのにと、しみずみと感じてしまいました。
但し、htmlspecialcharsで変換される、タグは以下の通りです。
& (アンパサンド) → &amp;
< (小なり) → &lt;
> (大なり) → &gt;
" (ダブルクオート) → &quot;
' (シングルクオート) → &#039; または &apos;(ただし、$flags によって異なる動作をする場合があります)
[あとがき]
htmlspecialcharsで変換できる特殊文字は、以上5種類だという話をしましたが、実は文字表記としては、今日までの調べでは、252種類あります。
252種類の文字表記すべてに&(アンバサンド)がついており、その対応は実は自分でしなければなりません。本日は、その対応に半日近く使ってしまいました。明日は、今日の続きと言うことでそのことを話しましょう!
では、また!!!
【このカテゴリーの最新記事】