事の発端
HTMLの属性値は、ダブルクォーテーションで囲うものだばかりと思っていたが、
シングルクォーテーションでもよいらしいと知った。
<p class="foo">content</p>
<p class='foo'>content</p>
ひらめいた
今まで、PHPの文字列内にHTMLコードを埋め込む際、文字列全体をシングルクォーテーションで囲っていた。
$html = '<p class="foo">content</p>';
なぜなら、属性値を囲うダブルクォーテーションをエスケープするのが嫌だったからだ。
視認性が落ちるし、抜け漏れの恐れもある。
$html = "<p class=\"foo\">content</p>";
ただ、変数が入ってくると、面倒だ。
変数の前後で文字列を一旦閉じて、ドット演算子で変数と連結して・・・
とやるのは、変数がいくつもあると面倒だし、何よりスマートじゃない。
$class = "foo";
$html = '<p class="'.$class.'">content</p>';
ダブルクォーテーションの中であれば、{}で囲うことで変数を展開できるので、できれば使いたい。
$name = "foo";
$str = "My name is {$name}.";
しかし、ダブルクォーテーション in ダブルクォーテーションだと、やはり視認性が・・・。
$class = "foo";
$html = "<p class=\"{$class}\">content</p>";
これが、今までの葛藤だった。
しかし、属性値をシングルクォーテーションで囲えるのならば、話は違う。
$class = "foo";
$html = "<p class='{$class}'>content</p>";
大分見やすい。
しかし
属性値をシングルクォーテーションで囲ったHTMLコードを見たことがなかった。
何か理由があるのではないかと調べてみたところ、主に2つの理由がありそうだ。
- 英語圏では、シングルクォーテーションと同じ ' を省略記号として使う。I'm fine. のように。そのため、区切り文字として使用する記号は、慣例的にダブルクォーテーションになった、という説。
- XSS対策として、PHPではhtmlspecialchar()及びhtmlentities()が使用される。これらのメソッドは、デフォルトではシングルクォーテーションをエンティティ文字列に変換しない。引数で指定をすれば変換することもできるが、デフォルトのままで変換されない場合を考慮して、ダブルクォーテーションで囲んでおいた方が安全という説。
結論
- 業務上、マークアップ済みのHTMLコードをいただき、PHPで処理を加えることが多いため、納品されたデータに合わせるのが筋。その場合、属性値はダブルクォーテーションで囲われている確率が高い。
- 個人的にマークアップするのであれば、シングルクォーテーションでもよいと思った。
- htmlspecialchar()及びhtmlentities()には、ENT_QUOTESを指定して、ダブルクォーテーションもシングルクォーテーションもエンティティ変換するようにする。
追記
よく考えてみたら、業務上、「HTMLコードを組み立てて返す」といった処理はせず、もっぱらviewでHTMLにPHPタグを埋め込んでいる。
<?php
$class = "foo";
if(true) {
?>
<p class="<?php echo $class; ?>">content</p>
<?php
}
?>
これだと、そもそも影響は受けない。