[PHP]htmlspecialchars()を使うと文字が消える?

HTMLとして文字を出力する際によく使われる htmlspecialchars() ですが、
使った時に変数の内容が全て消えてしまう時があります。

<?php
mb_internal_encoding('UTF-8');
$text = "これはテストです";
$text = mb_convert_encoding($text, 'SJIS', 'UTF-8');
echo htmlspecialchars($text, ENT_QUOTES);

上記サンプルは UTF-8 で保存されたプログラムです。
文字を mb_convert_encoding() で Shift_JIS に変換して出力しようとしていますが、文字は全く表示されません。

解決方法は htmlspecialchars() の第 3 引数を省略しないで指定することです。
第 3 引数には文字エンコーディングを指定します。上記の場合は、次のように指定することで適切に表示することができます。

htmlspecialchars($text, ENT_QUOTES, 'SJIS')

この引数を省略すると、PHP 5.4.0 より前のバージョンでは ISO-8859-1 、PHP 5.4.0 以降では UTF-8 が指定されます。
そして、指定されたエンコーディングとして有効でない文字は切り捨てられます。

一応 ENT_IGNORE を 第 2 引数(flags)に指定することでもこの切り捨てを回避することはできますが、XSS(クロスサイトスクリプティング)などの脆弱性を生む可能性があるので使うべきではありません。