Zend_View with HTML_Template_Flexy が意外と簡単だった件

Zend_View with HTML_Template_Flexy が意外と簡単だった件

Zend_ViewからSmartyを使うクラスはネット上を検索すると結構出てくるんだけど、Zend_ViewとHTML_Template_Flexyを組み合わせたクラスはなぜか全然見つからない。

Zend_View + Flexyを使いたい人っていないのかなーとか思いながら、適当にZend_ViewとFlexyを組み合わせてみたら、思った以上に簡単に作ることができてしまって驚いた。

とりあえず、↓のようなクラスを使えば、一応動くものができてしまう。

<?php
require_once 'Zend/View.php';
require_once 'HTML/Template/Flexy.php';

class My_View extends Zend_View_Abstract
{
    protected function _run()
    {
        $flexy = new HTML_Template_Flexy();
        $flexy->compile(func_get_arg(0));
        $flexy->outputObject($this);
    }
}

たったこれだけ。Zend_View_Abstractは、_run()を実装してやるだけで、残りの部分はほとんどやってくれるからありがたい。一応↑だけでも動くが、getEngine()は実装しておいたほうが後々幸せなようなので、↓のようにしておいたほうがいいかも。

<?php
require_once 'Zend/View.php';
require_once 'HTML/Template/Flexy.php';

class My_View extends Zend_View_Abstract
{
    private $_flexy;

    public function __construct($config = array())
    {
        parent::__construct($config);
        $this->_flexy = new HTML_Template_Flexy();
    }

    public function getEngine()
    {
        return $this->_flexy;
    }

    protected function _run()
    {
        $this->_flexy->compile(func_get_arg(0));
        $this->_flexy->outputObject($this);
    }
}

このMy_Viewクラスを、Zend FrameworkのMVCと組み合わせて使うには、起動ファイルで↓のように書けばよい。

<?php
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

//コンパイルディレクトリの指定は必要
$options = &PEAR::getStaticProperty('HTML_Template_Flexy', 'options');
$options = array('compileDir'  => '/path/to/compile/directory');

$renderer = new Zend_Controller_Action_Helper_ViewRenderer(new My_View());
Zend_Controller_Action_HelperBroker::getStack()->offsetSet(-80, $renderer);
Zend_Controller_Front::run('/path/to/controller/directory');

これだけで、Zend_Controller クイックスタートの例とほぼ同じままで、ビュースクリプトには↓のようなFlexyスタイルのテンプレートを使うことができるようになる。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>{title}</title>
  </head>
  <body>
    <h1>{title}</h1>
    <p flexy:if="error">{error}</p>
    <ul>
      <li flexy:foreach="items,item">{item}</li>
    </ul>
  </body>
</html>

ビュースクリプトの決定や描画の指示は全部Zend_ViewやZend_Controller_Action_Helper_ViewRendererがやってくれるので、テンプレートディレクトリを指定する必要すらない。Controllerでやらなければいけないのは、↓のように普通のZend_Viewを使ったときと何も変わらない。

<?php
class IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $this->view->title = 'My_ViewTest';
        $this->view->error = 'No error happend.';
        $this->view->items = array('Item 0', 'Item 1', 'Item 2');
    }
}

これは便利。

ただし、

この仕組みには実は致命的な弱点が二つほどあって、実用化するのはちょっと苦しかったりする。

一つ目の問題は、テンプレート側で{method()}というテンプレートを書いた場合、Flexyの仕様では↓のようにコンパイルされる点。

<?php if ($this->options['strict'] || (isset($t) && method_exists($t, 'method'))) echo htmlspecialchars($t->method());?>

ご丁寧にmethod_exists()をはさんでくれるせいで、__call()を使って呼んでいるZend_Viewのヘルパーファンクションがことごとく使えない。これではurlヘルパーのようにMVCに直結した便利な関数は使えないし、Zend_FormやZend_Layoutといったクラス群も使えなくて、とても不便だ。

とはいえ、この問題はstrictオプションをtrueに設定すれば回避できそうだからまだいい。本当に致命的な問題は、Flexyの仕様で{method()->property}のような記法が使えなくて、メソッドの返り値のオブジェクトのプロパティを取得できない点。これでは、仮にヘルパーファンクションが呼び出せたとしても、layout()->contentのような記述が使えないので、結局Zend_Viewが持つ多くの機能を諦めざるを得なくなる。これはとても残念。

何とか回避できないのかなーと思っていろいろと探してみたけれど無理そう。結局のところ、HTML_Template_FlexyをZend_Viewで使いたければ、Zend_Viewの機能はほとんど諦めて、HTML_Template_Flexyの機能を中心に使っていくしかないようだ。(Flexyが持つフォーム管理機能がZend_Viewと一緒ではうまく使えなかったりするかもだけど。)

結論

  • Zend_ViewでHTML_Template_Flexyを使うこと自体はとても簡単です
  • ただし、Zend_Viewの優れた機能はあまり活用できなくて、HTML_Template_Flexyの機能を最大限に使うしかなさそうです
  • Zend_Viewとの相性の善し悪しは、ヘルパーファンクションをどれだけ上手に扱えるかにかかっているようです
スポンサーサイト



関連記事

トラックバック URL

http://liosk.blog103.fc2.com/tb.php/145-e85a30f8

トラックバック

コメント

コメントの投稿

お名前
コメント
編集キー