htmlヘルパーlinkはリンク文字列をHTMLエンティティ化する

想定外。

Sanitize::html()でエンティティ化した文言を、$html->linkでリンクすると、リンク文字列がアンエスケープされず、エンティティのまま表示されました。

正(ホームで名前表示@文言リンクなし)
<i>italic</i>(+-"1")

誤(一覧で名前表示@文言リンクあり)
&lt;i&gt;italic&lt;/i&gt;&#40;&#43;&#45;&quot;1&quot;&#41;

これは$html->linkのデフォルト挙動で「aタグ内の文字列はHTMLエンティティ化する」のが原因でした。


つまり、$html->linkをデフォルトの引数設定だけで使うと、「画像リンク」とかは作成できないんだよ、という事を肝に銘じつつ。


htmlヘルパーをどこまで使うか、考え中です・・・・。


linkメソッドの中身を見て原因追究。第5引数の
$escapeTitle = true -> false
指定で解決しそうなのですが・・・

cake/libs/view/helpers/html.php

function link($title, $url = null, $htmlAttributes = array(), $confirmMessage = false, $escapeTitle = true) {
(中略)
	if ($escapeTitle === true) {
		$title = h($title);
	} elseif (is_string($escapeTitle)) {
		$title = htmlentities($title, ENT_QUOTES, $escapeTitle);
	}

他の引数次第で $escapeTitleがデフォルトの true以外の値に書き換わるケースもありますが、

通常の設定なら

if ($escapeTitle === true) {
	$title = h($title);

を通る。

function h()は、cakePHP独自のhtmlspecialchars拡張(?)
cake/basic.php

function h($text, $charset = null) {
	if (is_array($text)) {
		return array_map('h', $text);
	}
	if (empty($charset)) {
		$charset = Configure::read('App.encoding');
	}
	if (empty($charset)) {
		$charset = 'UTF-8';
	}
	return htmlspecialchars($text, ENT_QUOTES, $charset);
}


さらに、HTMLエンティティされたままのリンク部分のソースを見ると

&amp;lt;i&amp;gt;italic&amp;lt;/i&amp;gt;&amp;#40;&amp;#43;&amp;#45;&amp;quot;1&amp;quot;&amp;#41;

なので、

& → &amp;

に変換されてるのが原因。


ということで、$escapeTitle = false の指定で解決!


・・・・とは、言い切れず。。。

  • 今後のビュー全体で、「この変数はHTMLエンティティ化してるかどうか」を判断して第5引数まで指定するのか?

・・・そういう方法も、ありですが。

  • htmlヘルパー使うのやめる?


考え中です。