しかし、PHP 5.4で忘れられがちないくつかの特に重要な変更により、ほとんどのhtmlspecialcharsが大胆にカタフレーズ(StackOverflowのArtefacto)に書き換えられました。
問題の変更は、htmlspecialcharsだけでなく、htmlentities、htmlspecialchars_decode、html_entity_decode、get_html_translation_tableも参照します。
最も重要な変更の概要は次のとおりです。
- UTF-8デフォルトエンコーディング
- エラー処理の改善(ENT_SUBSTITUTE)
- Doctype処理(ENT_HTML401、...)
UTF-8デフォルトエンコーディング
ご存知のように、htmlspecialcharsの3番目の引数はエンコードです。 ほとんどの人はこの引数を単に見逃しているため、デフォルトのエンコーディングを取得しています。 この値は、PHP 5.4までISO-8859-1でした。 新しいバージョンでは、UTF-8をデフォルトにすることでこれを修正しています。
エラー処理の改善
5.4までのhtmlspecialcharsのエラー処理は...うーん、「直感的ではない」と呼びましょう。
「不正なコードシーケンス」を含む文字列を指定した場合(Unicodeの場合は「不正にエンコードされた文字列」です)、htmlspecialcharsは空の文字列を返します。 まあ、大丈夫、これまでのところとても良い。 おかしなことは、 エラー表示が無効になっている場合にのみ、さらにエラーが発生することです。 素晴らしいですね。
これは基本的に、開発用コンピューターではエラーが表示されないことを意味しますが、運用環境ではエラーログにエラーが書き込まれます。 すごい
幸いなことに、PHP 5.4では、この動作はすでに歴史的です。 エラーは生成されなくなります。
さらに、返される空の文字列の代替を指定できる2つのオプションがあります。
- ENT_IGNORE:このオプション(これは実際には新しいものではなく、PHP 5.3で使用されていました)は、誤ったコードシーケンスを破棄するだけです。 これには2つの理由があります。まず、無効な文字は表示されません。 第二に、これは特定のセキュリティリスクをもたらします 。
- ENT_SUBSTITUTE:これは新しい代替オプションです。 文字を削除するだけでなく、Unicodeの代替文字(U + FFFD)に置き換えられます。
さまざまな動作を見てみましょう( demo ):
<?php // "\80" UTF-8 var_dump(htmlspecialchars("a\x80b")); // string(0) "" var_dump(htmlspecialchars("a\x80b", ENT_IGNORE)); // string(2) "ab" var_dump(htmlspecialchars("a\x80b", ENT_SUBSTITUTE)); // string(5) "a b"
明らかに、後者のオプションが望ましいです。 実際のアプリケーションでは、次のようになります。
<?php // bootstrap, 5.3 if (!defined('ENT_SUBSTITUTE')) { define('ENT_SUBSTITUTE', 0); // 5.3 // define('ENT_SUBSTITUTE', ENT_IGNORE); // 5.3 } // 5.3 $escaped = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
Doctype処理
PHP 5.4には、使用するdoctypeを示す4つの追加フラグがあります。
- ENT_HTML401(HTML 4.01)=>デフォルトで使用
- ENT_HTML5(HTML 5)
- ENT_XML1(XML 1)
- ENT_XHTML(XHTML)
指定するdoctypeに応じて、htmlspecialchars(および他の関連する関数)は異なるエンティティテーブルを使用します。
例( demo ):
<?php var_dump(htmlspecialchars("'", ENT_HTML401)); // string(6) "'" var_dump(htmlspecialchars("'", ENT_HTML5)); // string(6) "'"
したがって、HTML 5の場合、エンティティ&apos; が返されますが、HTML 4.01の場合-&apos;をサポートしていないため -数値コード&#039;。
htmlentitiesを使用すると、より多くの違いがあるため、違いがより明確になります。
これは、生の変換テーブルを見ると簡単に確認できます。
これを行うには、get_html_translation_table関数を使用できます。 XML 1 Doctypeの例( demo )は次のとおりです。
<?php var_dump(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES | ENT_XML1));
実行結果:
array(5) {
["""]=>
string(6) """
["&"]=>
string(5) "&"
["'"]=>
string(6) "'"
["<"]=>
string(4) "<"
[">"]=>
string(4) ">"
}
これは私たちの期待に沿ったものです。XMLのみが5つのコアエンティティを定義しています。
HTML 5( demo )でも同じことを試してみましょう。次のようなものが表示されます。
array(1510) {
[" "]=>
string(5) "	"
["
"]=>
string(9) "
"
["!"]=>
string(6) "!"
["""]=>
string(6) """
["#"]=>
string(5) "#"
["$"]=>
string(8) "$"
["%"]=>
string(8) "%"
["&"]=>
string(5) "&"
["'"]=>
string(6) "'"
// ...
}
HTML 5は、正確には1510という多数のエンティティを定義しています。 また、HTML 4.01とXHTMLを指定してみてください。どちらも253個のエンティティを定義しています。
また、選択したドキュメントタイプの影響を受けるのは、上で言及しなかった別の新しいエラー処理フラグENT_DISALLOWEDです。 このフラグは、文字をUnicode置換文字に置き換えます。これは、正式には正しいコードシーケンスですが、このDOCTYPEでは許可されていません。
したがって、返される文字列がコーディングに関してこの形式で常に整形式であることを保証できます。 このフラグの使用がどれほど役立つかはわかりませんが。 とにかくブラウザは無効な文字を適切に処理するので、これは私には不要なようです(おそらく間違っていますが)。
それだけではありません
...しかし、ここにすべてをリストしたくありません。 上記の3つの変更は、最も重要な改善点だと思います。
<?php htmlspecialchars("<\x80The End\xef\xbf\xbf>", ENT_QUOTES | ENT_HTML5 | ENT_DISALLOWED | ENT_SUBSTITUTE, 'UTF-8');