目次

PHP 簡易的なテンプレートエンジンその2

外部テンプレートファイルを読み込み、テンプレート中の専用タグと同じ名前を持った配列を内容を出力する簡易的なテンプレートエンジンです。(テンプレートエンジンなどと言っていますが配列を展開してるだけで特殊な機能はありません)

テンプレートはテキストとして読み込んでpreg_replaceで文字置換しているので処理速度は低速でPHP構文も使えません。しかしテンプレート中でPHPが使えないのでPHP構文エラーによるトラブルはありません。

2018/12/31 PHP7用のコード追加


イメージ

テンプレート(専用タグ)データ(php)
<h1>{{title}}</h1>
<p>{{text}}</p>
$datas{'title'}='デモ';
$datas{'text'}='Hello world!'
↓結果
<h1>デモ</h1>
<p>Hello world!</p>

「その2」となっていますが前回とはコンセプトが違い、できるだけ特殊な機能は一切含まずシンプルに入力されたデータを出力するようにしましたので関数本体はたった3行だけです。

function template_engin2($data,$array){
  return preg_replace_callback('/\{\{(.*?)\}\}/',function($match)use($array){return $array[$match[1]];}, $data);
}

※PHP5.xなど上記が動作しない場合は下記を使用

function template_engin2($data,$array){
  return preg_replace('/\{\{(.*?)\}\}/e','$array[\'$1\']' , $data);
}

サンプル

phpの実行できる環境で、次のPHP(template2.php)とテンプレート部(template2.html)をダウンロードし、同じディレクトリに置いてphpを実行して下さい。

template2.php
<?php
  // ---------- 簡易テンプレートエンジン関数 ---------- 
  function template_engin2($data,$array){
    return preg_replace_callback('/\{\{(.*?)\}\}/',function($match)use($array){return $array[$match[1]];}, $data);
  }
  // ---------- 関数終了----------
 
  // テンプレートファイルの読み込み
  $temp_body = file_get_contents('template2.html');
 
  // テンプレートに出力するデータ(xssに注意:次項参照)
  $temp_datas=array();
  $temp_datas['title']=htmlspecialchars('デモタイトル',ENT_QUOTES,'UTF-8');
  $temp_datas['data']=htmlspecialchars(date("Y/m/d H:i:s"),ENT_QUOTES,'UTF-8');
  $temp_datas['text']=htmlspecialchars('Hello World!',ENT_QUOTES,'UTF-8');
  $temp_datas['html']='<a href="http://www.google.co.jp/">Google</a>';
 
  //テンプレート関数実行
  echo template_engin2($temp_body,$temp_datas);
template2.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>{{title}}</title>
</head>
<body>
  <h1>{{title}}</h1>
  <p>日付:{{data}}</p>
  <p>通常文書:{{text}}</p>
  <p>HTML文書:{{html}}</p>
  <p>未使用キーは除去:{{hogehoge}}</p>  
</body>
</html>

注意点

1.外部ユーザーが操作できるデータを挿入する時は、配列に代入する時にxss対策を行って下さい。xss対策で無害化しないと悪意のあるスプリクトなどが設置可能になります。(上記例では$temp_array['html']以外はhtmlspecialchars関数にて最低限の無害化はしてありますが、scriptタグの内側やHTMLタグ属性などに専用タグを設置する場合は別途javascript等を無効化する対策が必要です)

2.テンプレート本体の {{文字列}} は除去されます。表示したい場合は「{&#123;」「}&#125;」にエスケープして疑似的に表示するか、カッコを直接出力したい場合はテンプレートのデータに「$temp_datas['left_tag']='{';」「$temp_datas['right_tag']='{';」のように登録し、テンプレート本体側に{{left_tag}}{{right_tag}}タグを設置して下さい。