CakePHP では、意外なところに例外的な措置があって、思わぬ事態に遭遇することがあります。知っていれば便利な機能も、知らないと逆に不便。
今回は、Controller::set で、’title’ をキーにしてViewに値を渡そうとして発覚。
‘title’ というキーは、Controller::set で特別な意味を持ちます。
すなわち、’title’ というキーで変数をセットした場合、Viewファイル内で $title として展開されず、レイアウトファイルの $title_for_layout ( ページタイトル) として展開されます。
/**
* Saves a variable for use inside a view template.
*
* @param mixed $one A string or an array of data.
* @param mixed $two Value in case $one is a string (which then works as the key).
* Unused if $one is an associative array, otherwise serves as the values to $one's keys.
* @return void
* @access public
* @link http://book.cakephp.org/view/427/set
*/
function set($one, $two = null) {
$data = array();
if (is_array($one)) {
if (is_array($two)) {
$data = array_combine($one, $two);
} else {
$data = $one;
}
} else {
$data = array($one => $two);
}
foreach ($data as $name => $value) {
if ($name === 'title') {
$this->pageTitle = $value;
} else {
if ($two === null && is_array($one)) {
$this->viewVars[Inflector::variable($name)] = $value;
} else {
$this->viewVars[$name] = $value;
}
}
}
}
この25行目を見ると明らかですが、つまり、コントローラーで ‘title’というキーで値をセットしても、Viewには渡らないということです。なので、この箇所をオーバーライドするか、別のキーで値を渡すようにしなくてはなりませんね。
ただ、こんな肝心なメソッドを上書きしちゃうと、他のアプリの構築のときにまた勝手が変わって面倒なことになるのでそれはしたくないです。また、’title’という文字だけ特別扱いするというのも汎用性に欠けるため好ましくない(変数の構成が動的に変化する場合、必ずしも変数のキーを知っているとは限らないから)。
なので、今後 Viewに値を渡す場合は、常にハッシュでくるんで、Viewでそれを展開することにしたいと思っています。というか、これまではその方法だったのですが、今回初めて直接 ‘title’ というキーを用いたため気づきました。
このような親切設計も、その実装を知っていれば便利ですが、そうでない場合はかえって時間がかかって困ってしまいますね。