Zend Framework 2 で Smarty を使うためのモジュール

そういえばだいぶ前に Zend Framework 2 で Smarty を使うためのモジュールを作りました。

なお、ZfcTwig を大いに参考にしました。

最初に作ったのは1年ぐらい前だったと思います。その当時に GitHub とかで同じようなものを探してみたところ、いくつか見つかったのですが次のような点で手に馴染まない気がしたので作ることにしました。

  • phtml を完全に置き換えてしまう
    • 既存のモジュールで phtml を使っていると動かなくなる
  • コントローラーのアクションで SmartyModel などを返さなければならない
    • コントローラーでテンプレートエンジンを意識したくない
  • ビューヘルパーが呼べない
    • 呼びたい

なお、今改めて確認すると下記とか良い感じかも知れません。

インストール

Packagist に登録しているので composer でインストールできます。

$ composer require ngyuki/zf2-smarty:dev-master

インストールが終わったら vendor/ngyuki/zf2-smarty/config/smarty.global.phpconfig/autoload/ にコピーします。

$ cp vendor/ngyuki/zf2-smarty/config/smarty.global.php config/autoload/

そして config/autoload/smarty.global.php を編集します。

基本的には smarty の部分に Smarty のオプションを書けば OK です。ひな形のファイルは development な感じにしているので production ならそれっぽく変更が必要です。

<?php
return array(
    'smarty' => array(
        // here!
    ),
);

さらに config/application.config.phpZendSmarty を追記します。

<?php
return array(
    'modules' => array(
        'Application',
        'ZendSmarty', // this is it!
    ),

    // ...
);

使い方

既存の .phtml と同じ命名規則で、拡張子だけ .tpl に変更したファイル名で Smarty のテンプレートを作成します。

module/Application/view/application/index/index.tpl

<h1>I am smarty</h1>
<code>PHP {$smarty.const.PHP_VERSION}</code>

拡張子 .tpl でファイルが見つかれば Smartyレンダリングされます。見つからなければ .phtml がレンダリングされます。

ビューヘルパー

ビューヘルパーは次のように書けます。

{url home}
{url application [controller => index, action => index]}

これは .phtml での次のコードと同じです。

<?= $this->url("home") ?>
<?= $this->url("application", ["controller" => "index", "action" => "index"]) ?>

echo が不要な場合は次のように書けます。

{do headTitle "Index Page"}

これは .phtml での次のコードと同じです。

<?php $this->headTitle("Index Page") ?>

これらは Smartyコンパイラ関数プラグインで実現しているのですが、メソッドチェインには対応していません。

メソッドチェインしたい場合は $this を使います。

{$this->headTitle("ZF2 Smarty")->setSeparator(' - ') nofilter}

これは .phtml での次のコードと同じです。

<?= $this->headTitle("ZF2 Smarty")->setSeparator(' - ') ?>

テンプレート継承

ZfcTwig だとレイアウトとコンテンツの両方のテンプレートが Twig であれば ZF2 のレイアウト機能を使わずに Twig のテンプレート継承でレイアウトを実現することができます(zfctwig.disable_zf_model デフォルトで true)。

Smarty3 でもテンプレート継承はできますが、残念ながらわたしのモジュールは ZfcTwig のような機能は実装していません。

というのも、ZfcTwig を使っていたときに、すべてのビューで共通する値をアサインするために、

<?php
class Module
{
    public function onBootstrap(MvcEvent $ev)
    {
        /* @var $view \Zend\View\View */
        $view = $ev->getApplication()->getServiceManager()->get('View');
        $view->getEventManager()->attach(ViewEvent::EVENT_RENDERER_POST, function (ViewEvent $ev) {
            $ev->getModel()->val = 123;
        });
    }
}

と、したところ、ZfcTwig だと意図通りに動かなかったからです。

ZfcTwig でレイアウトとコンテンツのテンプレートが両方 Twig の場合、レイアウトのレンダリング時に独自にコンテンツのレンダリングを行うようになっており、コンテンツのレンダリングに関して EVENT_RENDERER_POST イベントが発生しないためです。

気になったのはこれだけですが、なんとなく他にもドハマりしそうなものが隠れている気がしたので封印することにしました。

なので、このモジュールでもそのような機能は設けていません(ZfcTwig のようにオプションで切替えられるならそれでもいいかな―と思いましたが、どうせ使わないし)。

さいごに

Zend Framework 2 のモジュール名やコンフィグのエントリ名ってベンダ名っぽいプレフィックスを付けるものみたいですね。

ZendSmarty という名前はよろしくなさそうなので、変えたほうが良いですね・・・・