Zend Framework と Smarty と Layout 機能その2
前回の続き。
Smarty での Layout 機能の使用方法は今回はウノウラボで紹介されている方式を使う。
つまりコンンテンツファイルを fetch メソッドを使用して、
取得したコンテンツを Layoutのテンプレートにアサインする。
Zend Framework と連携
Zend Framework と Smarty との連携は Zend_Controller_Action_Helper_ViewRenderer() を使用する。
Zend Framework と Smarty を連携 - Memo を参照。
※ ViewRender を使用しなくても出来るけど。。。
ブートストラップ
<?php // $this->_smartyConfig には template_dir などの Smarty の設定値が入っている $view = new Smarty_View(null, $this->_smartyConfig); $viewRender = new Zend_Controller_Action_Helper_ViewRenderer(); $viewSuffix = 'tpl'; $viewRender->setView($view) ->setViewSuffix($viewSuffix); Zend_Controller_Action_HelperBroker::addHelper($viewRender);
コントローラ
コントローラでの流れは以下のようになる。
- init() でコンテンツとなるテンプレートを取得する
- postDispatch() で取得したコンテンツを Layout のテンプレートにアサインする
- Layout テンプレートを fetch し表示する。
<?php class My_Controller_Action extends Zend_Controller_Action { protected $_request; protected $_module; protected $_controller protected $_dirs; protected $_controllerPath; protected $_action; protected $_layout; protected $_contents; /** * init * * @access public * @return void */ public function init() { $this->_request = $this->getRequest(); // 現在のモジュール名 $this->_module = $this->_request->getModuleName(); // 現在のコントローラ名 $this->_controller = $this->_request->getControllerName(); // コントローラのパス $this->_dirs = $this->getFrontController()->getControllerDirectory(); // モジュール名をキーにコントローラのパスを取得する $this->_controllerPath = $this->_dirs[$this->_module]; // 現在のアクション名 $this->_action = $this->_request->getActionName(); // レイアウトのパスを設定する // root のパス(本来はブートストラップで設定して、Zend_Registry に保存している) $rootDir = "ルートディレクトリのパス"; $layout = "Layout ファイルのあるディレクトリパス"; // コンテンツファイルのパス $this->_contents = $root . $this->_module . '/view/' . $this->_controller . '/' . $this->_action . '.tpl'; // 自動的にレンダリングしないようにする $this->_helper->viewRenderer->setNoRender(); } /** * postDispatch * * @access protected * @return void */ public function postDispatch() { parent::postDispatch(); $contents = $this->view->render($this->_contents); $this->view->setScriptPath($layout); $this->view->assign('contents', $contents); //echo $this->view->render($layout); $this->getResponse() ->setBody($this->view->render($layout)); } }
コントローラの init() でLayout テンプレートのファイルを取得し、
属性に保持する。同じくコンテンツのテンプレートも取得して、
属性に保持する。
Zend_Controller_Action_Helper_ViewRenderer() を使用すると、
自動的に /モジュール名/views/コントローラ名/ が
Smarty オブジェクトの templates_dir に設定される。
その為このままだと、Layout テンプレートが表示されず、
コンテンツのテンプレートが表示されてしまうので、
$viewRenderer->setNoRender() を使用し、自動レンダリングを
オフにする。
自動レンダリングがオフになったので、postDispatch() で
レンダリングする必要がある。で、レンダリングする前に、
setScriptPath() で Layout テンプレートを指定し、取得した
コンテンツをアサインすれば良い。
そして、echo でレンダリングしてやる。
ちなみに、各コントローラで値をアサインすると、
コンテンツの方のテンプレートに値がアサインされる。
今回あげた例では色々省略してあるけど、実際には Layout の
場所を各コントローラと同一のディレクトリに layout という
ディレクトリを作り、そこに コントローラ独自で使用する場合の
Layout を設置している。
また、各コントローラごとではなく、もっとグローバルに使いたい
場合もあるだろうから、その場合は、共通の Layout ファイルを
設置するディレクトリ作っている。
コントローラ独自の Layout を使用したい場合は、
コントローラで、setLayout('ファイル名'); とすれば、
Layout ファイルを置き換えるようにしている。
ちょっと泥臭いやりかたになってしまったけど、やりたいことが実現できたので良いかw
※ 2007/12/24 14:54 追記
レンダリングの方法が間違ってたので修正。
詳しくは、Zend Framework で Smarty をレンダリングする方法 - Memo 参照。。。