目次

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

外部テンプレートファイルを読み込み、テンプレート中の専用タグと同名の連想配列の内容を出力するだけの簡易的なテンプレートエンジンです。

includeを使ってないのでPHP構文を使った複雑な処理はできませんが、逆にテンプレート編集ではPHP構文エラーが発生しません。

大きな欠点は、表示する配列データの数だけ繰り替えし文字置換しているので配列(要素)が多くなると処理時間が大きくなる事です。特にテンプレートのファイルサイズも大きい場合には影響が大きくなります。


自作関数

入力された連想配列からキーとデータを分離し、データ部から専用タグの文字 {と} をエスケープして、テンプレートのキーと同名の専用タグを置換しています。

// ---------- 簡易テンプレートエンジン関数 ---------- 
function template_engin($html,$dataArray){
  // 入力データを順番に置換({と}は再帰的に処理しないようエスケープ)
  foreach ($dataArray as $key => $value){
    $value = str_replace( '{', '{', $value);
    $value = str_replace( '}', '}', $value);
    $html = str_replace( '{{'.$key.'}}', $value, $html);
  }
 
  // テンプレート上に残った専用タグを除去
  $html=preg_replace('/{{.*}}/','',$html);
 
  // 変換されたデータを返す
  return $html;
}

プログラム例

下記2つのファイルをPHPの動作するディレクトリに保存して、ブラウザでtemplate.phpを表示するとテンプレートの専用タグの一に出力データが表示されます。

template.php
<?php
  // ---------- 簡易テンプレートエンジン関数 ---------- 
  function template_engin($html,$dataArray){
    foreach ($dataArray as $key => $value){
      $value = str_replace( '{', '&#123;', $value);
      $value = str_replace( '}', '&#125;', $value);
      $html = str_replace( '{{'.$key.'}}', $value, $html);
    }
    $html=preg_replace('/{{.*}}/','',$html);
    return $html;
  }
 
  // ---------- メイン ---------- 
 
  // テンプレートファイルの読み込み
  $fileTemp = file_get_contents('template.html');
 
  // テンプレート出力用の連想配列初期化
  $dataArray=array();
 
  // 出力データを登録(外部ユーザーの入力値はhtmlspecialcharsする事)
  $dataArray['title']='デモタイトル';
  $dataArray['data'] =date("Y/m/d H:i:s");
  $dataArray['text'] =htmlspecialchars('Hello World!',ENT_QUOTES,'UTF-8');
  $dataArray['html']='<a href="http://www.google.co.jp/">Google</a>';
 
  //テンプレート関数実行
  $output=template_engin($fileTemp,$dataArray);
 
  //表示
  echo  $output;
template.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>

カスタマイズ

単純にデータを展開するだけだと芸が無いので「HTML許可選択」を追加行っています。専用タグのキー名の頭に@をつけるとHTML許可して、@が無ければHTMLを不許可にしています。

プログラム

下記のtemplate.phpとtemplate.htmlは同じフォルダに保存してください。(template.htmlはファイルパスを書き換えれば任意のディレクトリに移動できます)

template.php
<?php
  // ---------- 簡易テンプレートエンジン関数 ---------- 
  function template_engin($data,$array){
 
    foreach ($array as $key => $value){
      //html有効
      $html=$value;
      $html = str_replace( '{', '&#123;', $html);
      $html = str_replace( '}', '&#125;', $html);
      $data = str_replace( '{{@'.$key.'}}', $html, $data);
      //html無効
      $xss=htmlspecialchars($value,ENT_QUOTES,'UTF-8');
      $xss = str_replace( '{', '&#123;', $xss);
      $xss = str_replace( '}', '&#125;', $xss);
      $data = str_replace( '{{'.$key.'}}', $xss, $data);
    }
 
    //未変換タグ除去
    $data=preg_replace('/{{.*}}/','',$data);
 
    //変換されたデータを返す
    return $data;
  }
  // ---------- 関数終了----------
 
 
  // テンプレート出力用の連想配列初期化
  $temp_array=array();
 
  // テンプレートファイルの読み込み
  $temp_data = file_get_contents('template.html');
 
  // 適当に$output に配列名とデータを登録
  $temp_array['title']='デモタイトル';
  $temp_array['data']=date("Y/m/d H:i:s");
  $temp_array['text']='Hello World!';
  $temp_array['html']='<a href="http://www.google.co.jp/">Google</a>';
 
  //テンプレート関数実行
  $output=template_engin($temp_data,$temp_array);
 
  echo $output;
template.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>HTML不許可:{{html}}</p>
  <p>未使用キーは除去:{{hogehoge}}</p>  
</body>
</html>

説明

入力したテンプレートファイル中にある「{{title}}」や「{[html]}」などのタグを、配列変数$temp_array['title']や$temp_array['html']の内容に置き換えます。

専用タグ

問題点

1.配列が多くなれば変換速度は低下します。

2.テンプレートが長くなれば変換速度は低下します。

2.テンプレート中で「{{文字列}}」 はテンプレートタグと扱われますので使用できません。またテンプレートタグとして使用しなかった「{{文字列}}」は全て削除されます。テンプレートと中で「{{文字列}}」を表示したい場合は実体参照を利用して下さい(例:「&#123;&#123;文字列&#125;&#125;」)

3.挿入データ中の 「{」 と 「}」 は二重展開を防止するため「&#123;」と「&#125;」に置き換えられます。したがって挿入データ中で「{{タグ}}」を使用しても再展開されません。

4.キー名にはPHPの配列で認められている文字しか使えません(安全な文字列は英文字またはアンダースコアから始まり、英文字・数字・アンダースコアの文字列です)

更新 2018/09/13 挿入データのタグ文字(「{」「}」)のエスケープ方法を変更 : 以前は「{{」や「}}」の2回連続カッコを対象に文字列のみ実体参照に変換していましたが1文字でもエスケープするように変換しました。