Symfonyのview.ymlでtitleにギリシャ文字をhtml entityで設定しようとして困りました。
最初は、ギリシャ文字で、小文字のアルファを出力したかったので、下記のように書きました。
title: hito.in(α)
すると、&が&に変換されてしまうのです。さてどうしたものか。
困っている人が自分以外にいるはず、と信じて止まないワタクシは早速調べたのです。
大体、こんな感じでたどっていきました。
http://trac.symfony-project.com/ticket/401
誰か、困ってるよ。 ここも見てよ。See also #1488http://trac.symfony-project.com/ticket/1488
sfWebResponse.phpにパッチをあてたよ。
実際に手元のソース(sfWebResponse.php)をみてみると、
public function setTitle($title, $escape = true)
解決するのか!?と思いましたが、 sfWebResponse.phpのsetTitleという関数に、escapeをオンオフ(つまり&を&にするしない)するためのオプションをつけたよ、というものでした。
これは、$sf_response->setTitle(‘たいとる’, false);というようにプログラム内でタイトルを設定している場合に有効です。動的にページのタイトルをつける場合にはいいでしょう。
ただ、今回はview.ymlでデフォルトのタイトルをつけたいのでこのAPIには頼れません。
諦めてソースを解析します。
まず、view.ymlはどこで解析しているか。grepを使い、霊感を働かせて調べていくと、sfViewConfigHandler.phpに行き当たります。
sfViewConfigHandler.phpの中でページのメタ情報部分を扱うのはどこか。metaで検索して見つけます。
protected function addHtmlHead($viewName = '')
{
$data = array();
foreach ($this->mergeConfigValue('http_metas', $viewName) as $httpequiv => $content)
{
$data[] = sprintf(" \\$response->addHttpMeta('%s', '%s', false);",
$httpequiv, str_replace('\\'', '\\\\\\'', $content));
}
foreach ($this->mergeConfigValue('metas', $viewName) as $name => $content)
{
$data[] = sprintf(" \\$response->addMeta('%s', '%s', false, false);",
$name, str_replace('\\'', '\\\\\\'', preg_replace('/&(?=\\w+;)/', '&',
htmlentities($content, ENT_QUOTES, sfConfig::get('sf_charset')))));
}
return implode("\\n", $data)."\\n";
}
この関数の、2つ目のforeachでview.ymlのmetasブロックを解析しています。
さて、よく見てみると、 htmlentitiesを直接呼んでいます。ただ、そのあと、preg_replaceで&に直しています。
ということは、、ここでテストをしてみます。
_test("hito.in(α)");
_test("hito.in(α)");
function _test($string) {
printf(htmlentities($string, ENT_QUOTES, 'utf-8') . "\\n");
printf(preg_replace('/&(?=\\w+;)/', '&', htmlentities($string, ENT_QUOTE\
S, 'utf-8')) . "\n");
}
結果は、
hito.in(α) hito.in(α) hito.in(α) hito.in(α)
なるほどねぇ。
ということで、 Symfonyのview.ymlでtitleにギリシャ文字をhtml entityで設定したい場合は、数字を使ったエンティティではなく、アルファベットを使ったエンティティにしましょう。
数字を使ったエンティティを使いたい場合は、$sf_response->setTitle(‘たいとる’, false);を使うか、sfWebResponse.phpをハックするか、継承したクラスを作りましょう。