今日は、以前確認した「View」と「Controler」をさらに便利に使うことができる「ViewScript」についてのご紹介。

参考

本家様サイト-マニュアル ビュースクリプト
本家様サイト-マニュアル HTML自動生成

3日目4日目の日記で、「View」と「Controller」の役割について勉強したが、実際に開発をしていると、Viewでプログラム的な処理をしたい、ということが多々ある。
たとえば、顧客の一覧を出力するとき、1個ずつ出力するのは非常に効率が悪いので、配列をループさせて出力させたい。
たとえば、ユーザーごとで動的にページの内容が変化するとき、ユーザーの情報によって出力する、しないを切り替えたい。

こんなとき、Controllerで処理するか、無理やりViewで処理するか悩むところではあるのだが、こういうときは「ViewScript」を使うととてもしっくりと処理ができる。

そもそもViewScriptとは何か。

本家様サイト-マニュアル ビュースクリプトより

Curryではビュースクリプトと呼ぶ専用のクラスを定義することができます。
これはコントローラーと1対1で関連付くクラスで、コントローラーと同じようにアクションメソッドを定義します。すると、アクセスのあったコントローラーのアクションの処理の後、ビュースクリプトクラスのアクションメソッドが実行されます。
このビュースクリプトクラスではコントローラーでビューに対して設定されたビュー変数を参照、再代入することができるため、コントローラーで無加工でビューへ割り当てられたデータを加工する事ができます。

つまりどーゆーこっちゃ? という方向けに言えば、ContollerとViewの苦手な部分、すなわち「表示部分で、プログラム的な処理をしたい!」という要望に応えるためのものが「ViewScript」なんや!ということである。

それではさっそくViewScriptを使ってみる。

まずは非常にイケてないサンプルということで、Controllerは配列だけ取得して、Viewで配列を処理してしまった例。

site/controllers/index_controller.php

<?php
class IndexController extends Controller
{
public function index()
{
$this->view->userdata=array(
array(“username”=>”テスト太郎”,”age”=>29),
array(“username”=>”テスト次郎”,”age”=>38)
);
}
}

とりあえず、配列を適当に作って、Viewに渡す用の変数にセットしているだけである。
続いてView側。

site/views/layouts/default.php

<html>
<head>
<title>テストサイト</title>
</head>
<body>
<?php echo $inner_contents; ?>
</body>
</html>

layoutsフォルダは、サイトのデザインテンプレートを作って配置しておくことができる。
特に何も指定をしなければ、上記ファイルの内容を読み込み、「$inner_contents」変数を出力することでページごとのHTMLを出力することができる。引き続き、個別ページのView。

site/views/templates/index/index.php

<h1>顧客データ</h1>
<section>
<ul>
<?php foreach($userdata as $item) :?>
<li><?php echo $item[“username”]; ?> (<?php echo $item[“age”];?>)</li>
<?php endforeach; ?>
</ul>
</section>

そして出力されるHTMLはこんな感じ。

img1

一応目的は達成してるんだけども、Viewにロジック(ループ処理)が入っててダメな感じ。
これぐらい簡単なやつだったらまだ許容範囲、という人もいるかもしれないが、ifやswitchなどの様々な制御構造が複雑に絡み合うページの場合、ひじょーに見づらくなってメンテナンス性も悪いので、あまりお勧めできない。
といいつつ、自分も最初はViewに↑のような感じでゴリゴリと処理を書いてたのだけども。

それはともかく。
次は、ViewScriptを使い、そちらでロジックを処理してみる。
controller、テンプレートのdefault.phpは全く同じソースで行けるので省略。

site/views/templates/index/index.php

<h1>顧客データ</h1>
<section>
<?php echo $cust_output; ?>
</section>

先ほどと違い、ループ処理などのロジックはなく、単に変数を出力するだけのページになった。
そして、ViewScript。

site/views/scripts/index_view.php

<?php
class IndexView extends ViewScript
{
public function index()
{
        // HTML処理するクラスを読み込まないと、うまく処理できない。
        Loader::load(‘HtmlElement’, ‘html’);
$html_ul = new HtmlElement(“ul“);
foreach($this->view->userdata as $item) {
// LIタグ情報を新しく作って
$html_li = new HtmlElement(“li“);
// ULの中にLIタグを入れる
$html_ul->addElement($html_li);
// LIタグにテキストを追加しておしまい
$html_li->addText(“{$item[“username”]} ({$item[“age”]})”);
}
// 最後に、生成したHTMLデータをViewに引き渡す
$this->view->cust_output=$html_ul->getHtml();
// viewを省略してもよい。
//  $this->cust_output=$html_ul->getHtml();
}
}

これを実行すると、こうなる。

img2

顧客の一覧を出力するという業務処理を達成しつつ、Viewにはロジックを入れずにControllerでは表示に関与しないというサブ目標を達成するため、それらの仲介役として、表示に関するロジックを記載する概念「ViewScript」を用いることですべて丸く収まった。

最後に、今回唐突に出てきたHTML出力用のクラス「HtmlElement」については、ViewScript用のHTML制御クラスである。
こちらの用法については、本家様サイトのHTML自動生成にいろいろと掲載されているので、そちらも合わせてみてみると実際の業務に合わせた利用ができるのではないかと思う。