2015年10月30日金曜日

fuelphpでPresenterから、ベースとなるテンプレートの変数を代入する的なお話

  • このエントリーをはてなブックマークに追加

fuelphpでheaderやfooterが記載されたbase-template.phpをテンプレートとしたbase.phpというController_Templateを用意し、
それを継承したcontrollerで$this->template->contents = Presenter("index")みたいな感じでやって、
なんか面倒な処理をPresenter内でやるみたいな事はすごく便利ではあったりする。

けどこれってbase-template.phpのheader部分やfooter部分の変数を代入する事が出来ないっていう問題が発生する。
その場合base.phpのafterなりでごにょごにょするっていう方法もあるけど、動的なサイトの場合titleとかがんがん変わるわけで。
その度modelからControllerなりPresenterなりで処理したものをもう一度やるってなると無駄なわけで。

ってことで今回はそれを解決するための荒技を見つけたのでそのお話をば。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="keywords" content="<?php echo $keywords; ?>">
<meta name="description" content="<?php echo $description; ?>">
<title><?php echo $title; ?></title>
</head>
<body>

<?php echo $contents; ?>

</body>
</html>

とりあえずkeywordsとdescriptionとtitleを設置し、メインコンテンツを$contentsとして定義したテンプレート。


<?php

class Controller_Base extends Controller_Template{

  public $template = 'base-template';

  public function before(){
    parent::before();

    $this->template->set_global("title","title init");
    $this->template->set_global("keywords","keywords init");
    $this->template->set_global("description","description init");
  }

  public function after($response){
    $response = parent::after($response);
    
    return $response;
  }
}

このテンプレートを継承したcontrollerにはviews/base-template.phpをベースとして割り当てるよ的なやつ。
誰でもkeywordsやらtitleやらにアクセスしたいから、赤字で書いてるようにglobal化をする必要あり。


<?php

class Controller_Welcome extends Controller_Base{

  public function action_index(){
    $this->template->set_safe("contents",Presenter::forge("index")->render());
    $this->template->contents = Presenter::forge("index");
  }
}

Controller_TemplateであるController_Baseを継承したController。
views/base-template.phpを読み込んでおり、
$contents部分にviewを入れたいので、そこの処理をしている感じ。
通常時は打ち消し線で消されているように単純にPresenterを読み出すけど、
それだとwelcomeがbase-templateを読み込んで、
一旦処理が完了したらPresenterを読み込みことになってしまう遅延レンダリングだかなんだかになってしまう。
ってことでこれを防がないことにはPresenterから$titleなどに格納出来ないので、
ここで強制的にPresenterをレンダリングする必要がある。
そうすればPresenter内の処理が、welcome.phpの処理が完了する前に行う事が出来る。

ちなみにset_safeで読み込まないと強制レンダリングなのでエスケープされているので要注意。


<?php

class Presenter_Index extends Presenter{

  public function after(){
    $this->get_view()->set_global("keywords","keywords by presenter");
    $this->get_view()->set_global("title","title by presenter");
  }

  public function view(){
    echo "hoge";
  }
}

別にafterじゃなくてもbeforeでもいいし、viewでも問題はない。
先ほどwelcome.php内で書いたようにここでglobalな変数に対してsetする処理が行われる。



ってことでどうにか目的の事が出来たみたいな。
Presenter::forge("index")->set("hensu",$foo); これを見つけるまではcontroller内でPresenterで読み出されるviewsに対して挿入する変数を事前に入れておくという上みたいな処理をしていた。
で、base.phpのafterで$this->template->title = $this->template->contents->hensuみたいな形でやってたんだけど、
これだとそもそもPresenter使う必要ないじゃん的な無駄な感じではあったわけだし、
なんといっても処理が複雑になってくるとbase.phpのafter内が悲惨な事になってくるというかなんというか。
それに無駄にクエリを叩いてるわけでもあるし。

ということでこれでPresenter内で親の親の中にある変数に挿入したりなど出来て、コードが綺麗になるんじゃないかと。
Presenterが処理されるタイミングだとかそもそも遅延レンダリングと強制レンダリングってなんだとかそこら辺を知らないと難しいわけで。
とりあえずこれで見づらかった問題が解消出来た的な。

Adsense