Ethnaのテンプレートにレイアウトをかぶせる

| | コメント(0) |


テンプレートの共通部分(ヘッダー、フッター)などをメインのテンプレートから
include してたりしたんだけど、全部のファイルでinclude しないといけなくて面倒。
なので1つレイアウトファイルを作っておいてその真ん中にコンテンツ部分をはめ込む感じにしたい。


ちょっと苦しいけどEthna本体をいじらなくても、View のforwardをいじればなんとかなりそう。
まず、コントローラーのディレクトリ設定にレイアウトを追加。
app/APPID_Controller.php
    var $directory = array(
        // (snip)
        'layout'        => 'layout',
んで、View クラスに メソッド getLayout を追加。
テンプレート名を返す。
アクションごとにレイアウトを変えたい場合はそのアクションに対応したViewで別のレイアウトを返せばOK。

Viewのforward のなかみをごにょごにょこねくりまわす。

app/APPID_ViewClass.php
class APPID_ViewClass extends Ethna_ViewClass
{
    // レイアウトのテンプレート名を返す
    function getLayout ()
    {
        return 'Layout';
    }

    function forward()
    {
        $renderer =& $this->_getRenderer();
        $this->_setDefault($renderer);

        // メインの部分を取り出
        ob_start();
        ob_implicit_flush(0);
        $renderer->perform($this->forward_path);
        $html = ob_get_clean();

        // レイアウトがあれば取り出す
        $layout = $this->getLayout();
        if ($layout) {
            $dir = $controller->getDirectory('layout');
            $layout_file = $controller->getDirectory('layout') . '/' . $layout . '.'. $controller->getExt('tpl');
            ob_start();
            ob_implicit_flush(0);
            $renderer->prop = array(); // $renderer->clearProp();欲しい
            $renderer->setProp('contents', $html);
            $renderer->setProp('compornents', $compornents);
            $renderer->perform($layout_file);
            $html = ob_get_clean();
        }

        // 出力
        echo $html;
        return 0;
    }
}

ob_* 使い過ぎで美しくない。 $renderer->perform(); で結果を出力しないで 文字列で返すモードが欲しい。

あと CompornentView みたいなのやろうとすると viewのforwardも数回呼びたいから そっちも文字列で受け取りたい。

あとはlayout.tpl を用意してまんなかに {$contents} をはいちする。これメイン部分。
layout/layout.tpl
<html> 
<body> 
  {$contents}
</body> 
</html> 
templates/ja/index.tpl
<h1>タイトル</h1> 
<p> コンテンツ </p> 
こんな感じでイケるんじゃないでしょうか!

カテゴリ

,
 

コメントする