nazolabo

フリーランスのWebエンジニアが近況や思ったことを発信しています。

Ethnaの複合ビュー化を考える(1)

PHP勉強会ネタ。複合ビューってのは、Viewのheaderとかfooterが分離してるようなの(?)
まずViewが実際にtemplateを出力してるのは、Ethna_ViewClass.php

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

これ。
まあこの3行を呼べばとりあえず描画される。
とりあえず、複数のViewClassを結合して1つのViewClassになるようにする。このため、

  • 骨格
  • 骨格の内部

の2つのViewClassが必要となる。
PHP勉強会でらいあさんがやってた方法(http://events.php.gr.jp/event.php/event_show/15でスライドとソースが見れるよ!行ってない人もチェキ/ってかここリンクされてるよ!)は、骨格部分を設定変数にしてしまう方法だけど、微妙に面倒な気がしたので、ちょっといじる。
設定は、各ViewClassのメンバに以下のように記述する。

var $layout = array(
    'sidebar' => 'menu',
    'body' => 'list',
);

ハッシュの名前部分が変数名になり、値部分がViewの名前(Actionのreturnで渡す名前と同一)とする。
あとはこれを定義したViewのtemplateで

{$layout.sidebar}
{$layout.body}

とかすればいい。もちろんSmartyなので普通のHTMLも入れれる。
これを実装するにはAPPID_ViewClass.phpに

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

        if (property_exists($this, 'layout')) {
          $ctl = $this->backend->controller;
          $layout_vars = array();
          foreach($this->layout as $key=>$forward_name) {
            
            $view_class_name = $ctl->getViewClassName($forward_name);
            $view =& new $view_class_name($this->backend, $forward_name, $ctl->_getForwardPath($forward_name));
            
            ob_start();
            $view->preforward();
            $view->forward();
            $layout_vars[$key] = ob_get_contents();
            ob_end_clean();
          }
          
          $renderer->setProp('layout', $layout_vars);
        }

        $renderer->perform($this->forward_path);
    }

とする。
この方式は汎用性はあるものの、DRYっぽくない(骨格情報だらけになる)ので、Actionから呼ばれたViewは、コンテンツのメイン情報だけ入るようにして、ヘッダとかは勝手に入ってくる方式のほうが綺麗だと思う。結局Railsっぽくなるんだけど。rhacoのソースはまだ読んでない。