Zend_Layout
をよく使う。最もシンプルなレイアウトスクリプトを書くとこんな感じになる。
<?php echo $this->doctype() ?> <html> <head> <?php echo $this->headMeta() ?> <?php echo $this->headTitle() ?> <?php echo $this->headLink() ?> <?php echo $this->headStyle() ?> <?php echo $this->headScript() ?> </head> <body> <?php echo $this->layout()->content ?> </body> </html>
11行目では呼び出されたアクションコントローラに対応するビュースクリプトがレンダリングされる。例えばテキストフィールドのフォームを作り、ボタンをクリックしたら入力した文字列をダイアログに表示させるとしよう。コントローラスクリプトは以下のようにする。
// controllers/IndexController.php class IndexController extends Zend_Controller_Action { public function indexAction() { $this->view->id = "msg"; } }
ビュースクリプト側では変数id
が参照できるようになる。
// views/scritps/index/index.phtml <script type="text/javascript"> $(function() { $('form').submit(function() { alert($('#<?php echo $this->id ?>').value()); return false; }); }); </script> <form> <input type="text" id="<?php echo $this->id ?>" /> <input type="submit" /> </form>
期待通りの動作をするので悪くはないが、できることならばjQueryを実装する<script>
タグは、<body>
タグ内ではなく<head>
タグに納めたいところ。jQueryの実装を別のjsファイルに書く方法もあるが、アクションコントローラごとにjsファイルを作るのもバカバカしいし、jQuery部分にPHPコードを埋め込めるメリットがなくなってしまう。上記はあまり良い例ではないかもしれないが、HTMLとJavaScriptで共通する変数を扱いたいケースは少なからずある。
レイアウトスクリプトの修正
IndexControllerのindexAction()
メソッドに対応するビュースクリプトを例に挙げると、<body>
タグ内はindex.phtml
にコーディングして、<head>
タグ内に収めたいJavaScriptはindex.js
、CSSはindex.css
にコーディングできるようにしたいわけ。
まず、レイアウトスクリプトを以下の用に書き換える。
<?php echo $this->doctype() ?> <html> <head> <?php echo $this->headMeta() ?> <?php echo $this->headTitle() ?> <?php echo $this->headLink() ?> <?php echo $this->headStyle() ?> <?php echo $this->headScript() ?> <?php $javascript = $this->layout()->javascript; if(!empty($javascript)) : ?> <script type="text/javascript"> <?php echo $javascript ?> </script> <?php endif; ?> <?php $stylesheet = $this->layout()->stylesheet; if(!empty($stylesheet)) : ?> <style type="text/css"> <?php echo $stylesheet ?> </style> <?php endif; ?> </head> <body> <?php echo $this->layout()->content ?> </body> </html>
今まではindex.phtml
内にJavaScriptやCSSを埋め込むために、いちいち<script>
タグや<style>
タグなどを書く必要があったが、この部分もレイアウトスクリプトに含めてしまえば、若干ながらコーディング量も減らすことができる。
アクションヘルパーの実装
上記のレイアウトスクリプトでは、Zend_Layout
オブジェクトのjavascript
プレイスホルダにJavaScript部分が、stylesheet
プレイスホルダにCSS部分が、それぞれ格納されていることとしてる。これを実現するためのアクションヘルパーを実装していこう。
JavaScriptでもCSSでも、「Zend_Layout
の特定のプレイスホルダにレンダリングしたビュースクリプトの内容を格納する」という部分は共通しているので、まずは基底クラスとなるPartialView
アクションヘルパーを作る。
// controllers/helpers/PartialView.php class My_Action_Helper_PartialView extends Zend_Controller_Action_Helper_Abstract { public function render($name, $suffix, $action=null) { $renderer = clone Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); $renderer->renderBySpec($action, array('suffix' => $suffix), $name); } public function direct($name, $suffix, $action=null) { $this->render($name, $suffix, $action); } }
render()
メソッドの$name
はレンダリング結果を格納するZend_Layout
のコンテンツキーの名前、$suffix
は対応するビュースクリプトの拡張子、$action
は呼び出し元のアクションメソッド名となる。7行目では、ヘルパーブローカから、処理中のコンテキストで使われているViewRenderer
アクションヘルパーを複製している。なぜヘルパーブローカから取得したViewRenderer
を直接使用しないかというと、後続のrenderBySpec()
メソッドの呼び出しによって、処理中のコンテキストで使われているViewRenderer
に影響を及ぼしてしまうから。なお、$action
を明示的に指定しなかった場合、ViewRenderer
は処理中のコンテキストから対応するアクションメソッドを補完してくれる。
direct()
メソッドはアクションヘルパーのお決まりのパターン。render()
メソッドのエイリアスになっている。
続いて、JavaScriptをレンダリングするためのアクションヘルパーを作る。
// controllers/helpers/JsView.php require_once 'PartialView.php'; class My_Action_Helper_JsView extends My_Action_Helper_PartialView { public function direct($action=null) { parent::render('javascript', 'js', $action); } }
JsView
ヘルパーでは、direct()
メソッドだけをオーバーライドしている。PartialView
ヘルパーのrender()
メソッドを呼び出し、ビュースクリプト<action>.js
の内容をレンダリングした結果を、Zend_Layout
のjavascript
プレイスホルダに格納する。
CSSをレンダリングするアクションヘルパーも、同じように書くことができる。
// controllers/helpers/CssView.php require_once 'PartialView.php'; class My_Action_Helper_CssView extends My_Action_Helper_PartialView { public function direct($action=null) { parent::render('stylesheet', 'css', $action); } }
JsViewアクションヘルパーの使い方
冒頭で例に挙げたIndexController
のindexAction()
メソッドで、JsView
アクションヘルパーを使ってみよう。
// controllers/IndexController.php class IndexController extends Zend_Controller_Action { public function indexAction() { $this->view->id = "msg"; $this->_helper->jsView(); } }
これだけ。JavaScriptを実装したいアクションメソッドで$this->_helper->jsView()
を呼び出すだけ。CSSも同様に$this->_helper->cssView()
を呼び出すだけ。
あとは、対応するビュースクリプトを作ればいい。
// views/scritps/index/index.js $(function() { $('form').submit(function() { alert($('#<?php echo $this->id ?>').value()); return false; }); });
ビュースクリプトだから、当然PHPのコードを埋め込むこともできるし、$this
を経由してビュー変数にアクセスすることもできる。エディタによっては、拡張子に基づいて予約語などをハイライト表示してくれるので、言語別にファイルを分けられるのは重宝する。
index.phtml
もJavaScriptやCSSのコードが消えてスッキリ。
// views/scritps/index/index.phtml <form> <input type="text" id="<?php echo $this->id ?>" /> <input type="submit" /> </form>