デザイナーとプログラマーの共通言語 Smarty の導入と活用 <masahiro@asial.co.jp>
テンプレートエンジンの必要性 昔 (2000 年ごろ?) の典型的な PHP のコード : <?php // 処理?> <html> <body> <?php print("hello World!");?> </body> </html> 以下のような問題で衝突していた 1 一旦プログラムコードを埋め込んでしまうと デザイナーが HTML を修正できなくなる 2 プログラマーとデザイナーが同時に 1 つのファイルを修正して 衝突してします 3 デザインの見栄えを修正したくても プログラマーにお願いしないといけない
PHP をテンプレートエンジンにする 古典的ですが 今でもよく用いられます デザインとプログラムの分離は出来ていますし 速度も速いというメリットがあります ただし テンプレートエンジンと呼べるかは微妙です hoge.php <?php // プログラムコード require("hoge_template.php");?> hoge_template.php <?php // テンプレートコード?> <html> <body> <?=$var?> </body> </html>
PHP をテンプレートとして使うために PHP をテンプレートとして使うためには 以下の構文が便利です 変数を表示する <?=$var?> if 構文の別の書き方 <? if($aaa)?> true 時の処理 <? else;?> その他の処理 <? endif;?> for 構文の別の書き方 <? for ($i = 0; $i < 10; $i++):?> これは <?=$i?> 番目の処理です <? endfor;?> foreach 構文の別の書き方 <? foreach ($array as $key => $value):?> キー :<?=$key?> 値 :<?=$value?> <? endforeach;?>
テンプレートエンジンが生まれた背景 それでも デザイナーにとって コードが読みづらい ショートタグを使うのは 望ましくない 文書をフォーマットする という意味では使いづらい もう少し テンプレートを読み込んで処理する ことに主眼をおいたライブラリがあると良いのでは?
テンプレートエンジン登場 そこで テンプレートエンジンを使うと 以下のようなコードに変わります (Smarty の例 ) スクリプト側 (hoge.php) <?php require("common.php"); require("/path/to/libs/smarty.class.php"); $smarty = new Smarty(); $smarty->assign("var1", "Hello World"); $smarty->display("hoge.html");?> テンプレート側 (hoge.html) <html> <body> {$var1} </body> </html>
テンプレートを使った場合の作業フロー 開発時 共同作業 デザイナー デザイン作成 タグ打ち 完成 プログラマー ロジック作成 テンプレート埋め込み 修正時 デザイナー 修正依頼 テンプレート修正 完了 プログラマー ロジック修正
なぜ Smarty? 同じような動作をするテンプレートエンジンは数多くありますが 今回は Smarty に焦点を当てます 1 Smarty を使った事例が多い ( 一番メジャー 開発歴も長い ) 2 そこそこ良くできている ( ただしハマる所は知っておく必要あり ) 3 日本語のドキュメントが多い ( 日本語マニュアル 書籍も出ている )
テンプレートエンジンを使うメリット ビューを分離できる HTML コードとも見やすくなる( はず ) 便利機能がある
使わないメリット やっぱり遅くなる 最初のセットアップが大変 コンパイルキャッシュ周りの知識が必要
特徴的な機能 単にビューを分離するだけではなく いろいろな機能を持っています 関数 修飾子 キャッシュ ブロック カスタマイズ コンパイルキャッシュ 等々
Smarty の動作の仕組み 初回読み込み時 テンプレートファイル PHP ファイル内 次回以降 PHP ファイル内 読み込み パースコンパイル 保存 コンパイルキャッシュファイル 読み込み 出力 出力
Smarty のセットアップ 1. Smarty 本体をダウンロード (http://smarty.php.net) 2. ディレクトリに展開 3. templates ディレクトリ templates c ディレクトリを作成 ( デフォルトはスクリプトと同階層 ) 4. templates c ディレクトリに Apache から書き込める権限を付与 5. require ("/path/to/lib/smarty.class.php"); 6. $smarty = new Smarty(); で Smarty オブジェクトを作成 Smarty を使うためのコード <?php require("/path/to/libs/smarty.class.php"); $smarty = new Smarty(); $smarty->assign("var1", "Hello World"); $smarty->display("hoge.html");?>
Smarty の使い方 1 インスタンス作成 2 変数のアサイン 3 出力 or 取得 PHP 側 (hoge.php) <?php $scalar = "Hello World"; $array = array ("a" => "A", "b" => "B"); require("libs/smarty.class.php"); $smarty = new Smarty(); $smarty->assign("scalar", $scalar); $smarty->assign("array", $array); $smarty->display("hoge.html");?> テンプレート側 (templates/hoge.html) 変数を表示する場合 :{$scalar} 配列を表示する場合 :{$array.a} {$array.b}
Smarty の設定 $smarty オブジェクトのプロパティを修正して 各種設定ができる 設定の例 : // デバッグコンソールを出す ({debug} 関数でも可能 ) $smarty->debugging = true; // 各必須ディレクトリの場所の変更 $smarty->template_dir = "/path/to/template_dir"; $smarty->compile_dir = "/path/to/compile_dir"; // デリミタの変更 $smarty->left_delimiter = "{{"; $smarty->right_delimiter = "}}"; // コンパイルを強制する $smarty->force_compile = true;
Smarty 関数の使い方 PHP の関数とは別に Smarty 上で関数が利用できる これにより ビュー特有の処理を関数でまとめることができる 他のファイルを読み込む場合 : {include file=" ファイル名 "} foreach を使う場合 : {foreach from=$array key=key item=item} キー :{$key} 値 :{$item} {/foreach} そのほかにも いくつかの関数がデフォルトで用意されている また 自作で関数を作ることも可能
Smarty 修飾子 (modifier) の使い方 関数をより簡単にした形 Linux でいうパイプの役割をして 表現するデータに合わせて表示形式を変更できる 数値をフォーマットする場合 : {$value number_format} HTML エスケープを行う場合 (XSS 対策 ): {$value escape} また修飾子は重ねることが可能 : {$value escape nl2br} 引数を渡すことも可能 : {$value strip_tags substr:3}
自作関数の利用 関数 修飾子はカスタムで作ることができます 作り方には 2 通りあります プラグインに保存する場合 : 1 プラグイン用ディレクトリを作成し そのディレクトリを plugins dir として指定する $smarty->plugins_dir = array("plugins", "my_plugins"); 2 smarty function 関数名とした関数作成し smarty.function. 関数名という名称でプラグイン用ディレクトリに保存する <?php function smarty_function_imagetag ($params, &$smarty) { $filename = $params["filename"]; list($width, $height, $type, $attr) = getimagesize($filename); return "<img src= "$filename " $attr />"; }?> 3 関数を使う {imagetag filename="image.png"}
キャッシュ 初回読み込み時 PHP ファイル内 テンプレートファイル 読み込み 出力 次回以降 PHP ファイル内 保存 キャッシュ 読み込み 出力 キャッシュ機能を有効にする $smarty->caching = true;
Tips 1 クロスサイトスクリプティング脆弱性を強化する assign メソッドを改良し デフォルトで HTML エスケープされた状態で assign する class MySmarty extends Smarty { function assign($varname, $value) { $parent->assign($varname, htmlspecialchars($value, ENT_QUOTES)); } } $smarty = new MySmarty(); 2 テンプレート変数を連想配列で 1 つにまとめる assign メソッドを必要回数分記述するよりは $template var 等の変数に連想配列形式でテンプレート変数を割り当てると便利 $template_var["var1"] = "Hello World"; $template_var["var2"] = "hogehoge"; $smarty->assign($template_var);
SmartyDWT http://smartydwt.klitsche.org/ Dreamweaver から Smarty を簡単に操作するためのプラグイン
Template Lite(http://templatelite.sourceforge.net/) 以前 Smarty Light と呼ばれていたテンプレートエンジンを引き継ぐ形で 別の作者によって公開されているもの Smarty とほぼ同等の機能を備えている上 for や switch 関数などが追加されている
Simplate(http://simplate.aimy.jp/) Smarty の機能を PHP エクステンションの形で実現したもの 必要最低限の機能しか有していないが とても高速に動作する 変数のアサイン デリミタの変更 Smarty Simplate 関数 {function var=val} 形式 { 関数名 ($var)} 形式 修飾子 ループ処理 section,foreach section,foreach キャッシュ ( キャッシュ ID 対応 ) ( 出力の保存のみ ) 動作速度
ベンチマーク対決 Smarty Simplate TemplateLite で どの程度速度が異なるのか?PHP 5.1.4 で計測 PHP 側 (hoge.php) <?php $scalar = "Hello World"; $array = array ("a" => "A", "b" => "B", "c" => "C"); $smarty->assign("scalar", $scalar); $smarty->assign("array", $array); $smarty->display("hoge.html");?> テンプレート側 (templates/hoge.html) スカラー値 :{$scalar}<br> 配列 :{$array.a} {$array.b} {$array.c} <ul> {foreach from=$array item=a key=k} <li> キー :{$k} 値 :{$a}</li> {/foreach} </ul>
計測結果 ab n 1000 c 10 or 20 http://url 圧倒的にSimplateが高速 これは SimplateがPHPエクステンションとして動作するため 処理速度が速く また機能実装もシンプルであることが大きな要因だと思います
ご清聴 誠にありがとうございました