出力のエスケープ
ビュースクリプトで行うべき仕事のうち最も重要なもののひとつは、
出力を適切にエスケープすることです。これは、
クロスサイトスクリプティング攻撃を防ぐのを助けます。
それ自身がエスケープを行ってくれるような関数、メソッド、
あるいはヘルパーを使用しているのでない限り、
変数を出力する際には常にそれをエスケープしなければなりません。
Zend_View の escape() というメソッドが、このエスケープを行います。
// ビュースクリプトの悪い例
// ビュースクリプトのよい例
デフォルトでは、escape() メソッドは PHP の htmlspecialchars()
関数でエスケープを行います。しかし環境によっては、
別の方法でエスケープしたくなることもあるでしょう。
コントローラから setEscape() メソッドを実行することで、
エスケープに使用するコールバックを Zend_View に通知できます。
// Zend_View のインスタンスを作成します
// エスケープに htmlentities を使用するように通知します
$view->setEscape('htmlentities');
// あるいは、クラスの静的メソッドを使用するように通知します
'SomeClass', 'methodName'));
// あるいは、インスタンスメソッドを指定することもできます
'methodName'));
// そして、ビューをレンダリングします
コールバック関数あるいはメソッドは、
エスケープする値を最初のパラメータとして受け取ります。
それ以外のパラメータはオプションとなります。
別のテンプレートシステムの使用
PHP 自身も強力なテンプレートシステムではありますが、
開発者の多くは、デザイナにとっては高機能すぎる/複雑すぎる
と感じており、別のテンプレートエンジンをほしがっているようです。
Zend_View では、そのような目的のために二種類の仕組みを提供します。
ビュースクリプトを使用することによるものと、
Zend_View_Interface 実装することによるものです。
ビュースクリプトを使用したテンプレートシステム
ビュースクリプトを使用して、PHPLIB 形式のテンプレートのような
別のテンプレートオブジェクトのインスタンスを作成し、
それを操作できます。ビュースクリプトをこのように使用する方法は、
以下のようになります。
span style="color: #ff0000;">'template.inc'"booklist" => "booklist.tpl",
"eachbook" => "eachbook.tpl"'author', $this->escape($val['author''title', $this->escape($val['title']);
$tpl->parse("books", "eachbook""output", "booklist""nobooks", "nobooks.tpl")
$tpl->pparse("output", "nobooks");
}
関連するテンプレートファイルは、このようになります。
<!-- booklist.tpl -->
<table>
<tr>
<th>著者</th>
<th>タイトル</th>
</tr>
{books}
</table>
<!-- eachbook.tpl -->
<tr>
<td>{author}</td>
<td>{title}</td>
</tr>
<!-- nobooks.tpl -->
<p>表示する本がありません。</p>
Zend_View_Interface を使用したテンプレート
Zend_View 互換のテンプレートエンジンを使用するほうが簡単だという人もいるでしょう。
Zend_View_Interface では、
互換性を保つために最低限必要なインターフェイスを定義しています。
/**
* テンプレートエンジンオブジェクトを返します
*//**
* ビュースクリプト/テンプレートへのパスを設定します
*//**
* すべてのビューリソースへのベースパスを設定します
*/'Zend_View');
/**
* ビューリソースへのベースパスを追加します
*/'Zend_View');
/**
* 現在のスクリプトのパスを取得します
*//**
* テンプレート変数をオブジェクトのプロパティとして代入するためのオーバーロードメソッド
*//**
* テンプレート変数を手動で代入したり、複数の変数を
* 一括設定したりします
*//**
* 代入済みのテンプレート変数を削除します
*//**
* $name というテンプレートをレンダリングします
*/
このインターフェイスを使用すると、
サードパーティのテンプレートエンジンをラップして
Zend_View 互換のクラスを作成することが簡単になります。
例として、Smarty 用のラッパーはこのようになります。
span style="color: #808080; font-style: italic;">/**
* Smarty object
* @var Smarty
*//**
* コンストラクタ
*
* @param string $tmplPath
* @param array $extraParams
* @return void
*//**
* テンプレートエンジンオブジェクトを返します
*
* @return Smarty
*//**
* テンプレートへのパスを設定します
*
* @param string $path パスとして設定するディレクトリ
* @return void
*/'無効なパスが指定されました');
}
/**
* 現在のテンプレートディレクトリを取得します
*
* @return string
*//**
* setScriptPath へのエイリアス
*
* @param string $path
* @param string $prefix Unused
* @return void
*/'Zend_View'/**
* setScriptPath へのエイリアス
*
* @param string $path
* @param string $prefix Unused
* @return void
*/'Zend_View'/**
* 変数をテンプレートに代入します
*
* @param string $key 変数名
* @param mixed $val 変数の値
* @return void
*//**
* empty() や isset() のテストが動作するようにします
*
* @param string $key
* @return boolean
*//**
* オブジェクトのプロパティに対して unset() が動作するようにします
*
* @param string $key
* @return void
*//**
* 変数をテンプレートに代入します
*
* 指定したキーを指定した値に設定します。あるいは、
* キー => 値 形式の配列で一括設定します
*
* @see __set()
* @param string|array $spec 使用する代入方式 (キー、あるいは キー => 値 の配列)
* @param mixed $value (オプション) 名前を指定して代入する場合は、ここで値を指定します
* @return void
*//**
* 代入済みのすべての変数を削除します
*
* Zend_View に {@link assign()} やプロパティ
* ({@link __get()}/{@link __set()}) で代入された変数をすべて削除します
*
* @return void
*//**
* テンプレートを処理し、結果を出力します
*
* @param string $name 処理するテンプレート
* @return string 出力結果
*/
この例では、Zend_View ではなく
Zend_View_Smarty クラスのインスタンスを作成し、
それを使用して Zend_View と同じようなことをしています。
//例 1. InitializerのinitView()で
'/path/to/templates''ViewRenderer'':controller/:action.:suffix')
->setViewScriptPathNoControllerSpec(':action.:suffix')
->setViewSuffix('tpl');
//例 2. アクションコントローラでも同様に...
'Zend PHP 5 Certification Study Guide';
$this->view->author = 'Davey Shafik and Ben Ramsey'
}
}
//例 3. アクションコントローラでのビューの初期化
'/path/to/templates''viewRenderer'':controller/:action.:suffix')
->setViewScriptPathNoControllerSpec(':action.:suffix')
->setViewSuffix('tpl');
}
}