icon-attention デザイン新しくしました。

icon-calendar 2019年4月19日

【PHP】テンプレートエンジンのパーサ部分を簡単に作る

未分類

Twigなどのテンプレートエンジンにあるやつですね。

$name = 'mygod877';
という変数があったとしたら
私は{{ name }}です → 私はmygod877です


のように変換する機能をPHPのpreg_replace_callback関数を使って簡単に作っていきましょう。

ソースコード

まずはテスト用のテンプレートたち
今回は<?tag 変数 ?>を変換していきます。

template.tpl
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title><?tag title ?></title>
  </head>
  <body>
    <?tag header ?>
    <?tag contents ?>
    <?tag footer ?>    
  </body>
</html>

 

header.tpl
<header>
      Here is header.
    </header>

 

contents.tpl
<div class="contents">
      作者は<b><?tag author ?></b>です.
    </div>

 

footer.tpl
<footer>
      Here is footer.
    </footer></pre>
<pre>

 

index.php
<?php
$html = file_get_contents('template.tpl');
$data = array(
    'title' => 'ページのタイトル',
    'author' => 'mygod877'
);
echo parser($html, $data);

function parser($html, $data) {
    return preg_replace_callback('/<\?tag (.+?) \?>/', function($matches) use($data) {
        switch ($matches[1]) {
        case 'title':
            return $data['title'];
            break;
        case 'header':
            $header = file_get_contents('header.tpl');
            return parser($header, $data);
            break;
        case 'contents':
            $contents = file_get_contents('contents.tpl');
            return parser($contents, $data);
            break;
        case 'footer':
            $footer = file_get_contents('footer.tpl');
            return parser($footer, $data);
            break;
        case 'author':
            return $data['author'];
            break;
    }
    }, $html);
}

 

実行結果

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>ページのタイトル</title>
  </head>
  <body>
    <header>
      Here is header.
    </header>
    <div class="contents">
      作者は<b>mygod877</b>です.
    </div>
    <footer>
      Here is footer.
    </footer>    
  </body>
</html>

再帰関数を使っているので読込先のテンプレート内のタグも変換できます。

今回はテストで変換するタグも少ないためswitch文で書きましたが

数が多くなると大変なので連想配列を使ったテーブルサーチを検討してみてもいいかもしれませんね。