【PHP】nl2br()が動かなくて地味にハマった事について

【PHP】nl2br()が動かなくて地味にハマった事について

AWSシンプルアイコンを見るとキン消しを思い出します。fukasawaです。こんにちは。
こんな事言うと年齢がばれそうですね。

今回はPHPの小ネタです。PHPには改行文字(\r\n、\n\r、\n 、\r)を<br />に変換してくれる nl2br()という関数があります。この関数を使った部分が上手く動かず、地味にハマった事について書いてみたいと思います。

現象

先日、不具合のチケットを対応した際「登録が完了しました。\n対象件数は●件です。」というメッセージが画面に表示されているのを見つけました。「\n」がそのまま出力されているので、誰かが実装したときに変換し忘れたのだと思いソースコードを確認してみたのですが、

<?php echo nl2br($message); ?>

ちゃんと変換するよう記述されているようです。

原因

不具合の原因を調査して気づいたのですが、要するに下記のようなことでした。

$test = 'テスト\nテスト2\r\nテスト3';
echo nl2br($test);

// 出力:
// テスト\nテスト2\r\nテスト3

$test2 = "テスト\nテスト2\r\nテスト3";
echo nl2br($test2);

// 出力:
// テスト
// テスト2
// テスト3

「シングルクォートを使用した文字列の中にエスケープシーケンスが含まれていても特別な意味を持たない」というのはPHPの基本的な部分ですが、CakePHPのコントローラ内で定義された文字列がいろいろな処理を経てビューに辿り着きnl2br()に渡されたけれど、最初の定義がシングルクォートで行われていたため、上手く変換できなかったという、ただそれだけのことでした。
不具合になっていたのは、ダブルクォートで定義されていた文字列が何かのタイミングでシングルクォートに修正されてしまったのが原因のようです。

なんとなく「元の文字列がシングルクォートで定義されていても、ビルトイン関数に食べさせればいい感じにしてくれるんだろう」みたいな思い込みがあったので、そこもハマる要因のひとつだったように思います。

ちなみに、str_replace()

$test = 'a\nb\nc';
echo str_replace(["\r\n","\r","\n"], "<br>", $test);

// 出力:
// ba\nb\nc

$test2 = "a\nb\nc";
echo str_replace(["\r\n","\r","\n"], "<br>", $test2);

// 出力:
// a
// b
// c

同じですね。

参考

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ