LoginSignup
1
0

More than 1 year has passed since last update.

mb_convert_encoding()のHTML-ENTITIESの変換は逆変換できない

Posted at

mb_convert_encoding()の第2引数にHTML-ENTITIESを指定すると、文字列中の漢字やひらがななどをHTMLの文字実体参照・文字数値参照( ,€みたいなやつ)に変換してくれます。

「漢字やひらがななど」とあえてふわっと書きましたが、正確にはASCII (0x00-0x7F) の範囲外の文字が変換対象のようです(このあたりドキュメントが見つからなかったのでおそらくですが)。

逆に、第3引数にHTML-ENTITIESを指定すれば、文字実体参照などをデコードできます。

<?php
$string = 'あいうえお';
$encoded = mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
echo $encoded; // &#12354;&#12356;&#12358;&#12360;&#12362;
$decoded = mb_convert_encoding($encoded, 'UTF-8', 'HTML-ENTITIES');
echo $decoded; // あいうえお

上記のように、一度変換したあと逆向きに変換すれば元の文字列に戻せる……と思ってしまいそうですが、実はそうとは限りません。
先述したようにmb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8')で変換されるのはASCII範囲外の文字のため、ASCIIの文字は変換されません。つまり、&lt;のような文字列をUTF-8→HTML-ENTITIES→UTF-8と変換すると、2回目のみ変換されて<になってしまいます。

<?php
$string = '&lt;div&gt;あいう&lt;/div&gt;';
$encoded = mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
echo $encoded; // &lt;div&gt;&#12354;&#12356;&#12358;&lt;/div&gt;
$decoded = mb_convert_encoding($encoded, 'UTF-8', 'HTML-ENTITIES');
echo $decoded; // <div>あいう</div>

対策

これを防ぐためには、&&amp;に変換すればいいはずです。変換のタイミングはmb_convert_encoding()よりも前です。

<?php
$string = '&lt;div&gt;あいう&lt;/div&gt;';
$encoded = str_replace('&', '&amp;', $string);
$encoded = mb_convert_encoding($encoded, 'HTML-ENTITIES', 'UTF-8');
echo $encoded; // &amp;lt;div&amp;gt;&#12354;&#12356;&#12358;&amp;lt;/div&amp;gt;
$decoded = mb_convert_encoding($encoded, 'UTF-8', 'HTML-ENTITIES');
echo $decoded; // &lt;div&gt;あいう&lt;/div&gt;
var_dump($string === $decoded); // bool(true)
1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0