ビューの中で使用できる変数$htmlはどこからくるのか?
環境
この記事の内容は、CakePHP 1.1.12.4205で確認しました。
問題点
CakePHPでは、ビューの中で、例えば、
<?php echo $html->link('New Account', '/accounts/add'); ?>
のように、変数$htmlを使用することができますが、この変数$htmlがどこからきているのか気になったので、調べました。
調査結果
まず、CakePHPにおける基本的な処理の流れを確認します。CakePHPでは、app/webroot/index.phpでリクエストを受けますが、その最後で、
<?php (略) $Dispatcher = new Dispatcher(); $Dispatcher->dispatch($url); (略) ?>
として、Dispatcherクラスのdispatchメソッドを呼び出します。Dispatcherクラスは、cake/dispatcher.phpにあります。そのdispatchメソッドを抜き出すと、
<?php (略) function dispatch($url, $additionalParams=array()) { (略) return $this->_invoke($controller, $params, $missingAction); } (略)
であり、_invokeメソッドは、
<?php (略) function _invoke (&$controller, $params, $missingAction = false) { (略) $output = call_user_func_array(array(&$controller, $params['action']), empty($params['pass'])? null: $params['pass']); (略) $output = $controller->render(); (略) } (略)
のように、call_user_func_array関数を利用してコントローラのメソッドを呼び出し、その後、コントローラのrenderメソッドを呼び出しています。renderメソッドは、cake/libs/controller/controller.phpにあります。このメソッドは、
<?php (略) function render($action = null, $layout = null, $file = null) { (略) $this->__viewClass =& new $viewClass($this); (略) return $this->__viewClass->render($action, $layout, $file); } (略) ?>
のようになっており、ビューのクラスを生成して、renderメソッドを呼び出します。var_dump($viewClass)を挿入して実行してみたところ、$viewClassは"View"であることが分かりました。このクラスは、cake/libs/view/view.phpにあります。renderメソッドをみてみます。
<?php (略) function render($action = null, $layout = null, $file = null) { (略) $out = View::_render($viewFileName, $this->viewVars); (略) print $out; (略) } (略) ?>
このように、renderメソッドでは_renderメソッドを呼び出して、その結果を表示しています(ここでは、一般的な場合に処理されるコードを抜き出しています。場合によっては、違うこともあります)。では次に、_renderメソッドを読みます。
<?php (略) function _render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false) { if ($this->helpers != false && $loadHelpers === true) { $loadedHelpers = array(); $loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers); foreach(array_keys($loadedHelpers) as $helper) { $replace = strtolower(substr($helper, 0, 1)); $camelBackedHelper = preg_replace('/\\w/', $replace, $helper, 1); ${$camelBackedHelper} =& $loadedHelpers[$helper]; (略) } } (略) include ($___viewFn); (略) $out = ob_get_clean(); (略) return $out; } (略) ?>
まず始めにあるif文の中では、ヘルパーを読み込んでいます。ここで今回注目すべきところが、
<?php (略) ${$camelBackedHelper} =& $loadedHelpers[$helper]; (略) ?>
の文です。$camelBackedHelper変数には、"html"といった文字列が設定されています。つまり上の文は、
<?php (略) $html =& $loadedHelpers[$helper]; (略) ?>
と同じになります(foreach文の中にあるので、もちろん場合によります)。foreach文で初めて設定される変数ですが、PHPはforeach文の中だけのスコープは持たないので、この変数はforeach文を出た後でも有効です。その後、include ($___viewFn);でビューのファイル(*.thtmlです)を読み込み、HTMLを出力します。以上が、ビューの中で$html変数が使える理由です。