PHPのテンプレートエンジンを作ってみましたー。
symfony/templatingとか読んでたら急に作りたくなったw
インストール
Packagistに登録していないのでGitHubのrepositoryを設定してよしなにインストールします
$ composer config repositories.tzmfreedom/php-mytemplate-engine vcs https://github.com/tzmfreedom/php-mytemplate-engine
$ composer require tzmfreedom/php-mytemplate-engine:dev-master
使い方
Twigとかsymfony/templatingのPHPEngineとかと同じ使い方です。というかインターフェースを合わせました。
<?php
require_once 'vendor/autoload.php';
$engine = new \MyTemplate\Engine();
echo $engine->render("sample.my", ['xxx' => 'yyy']);
第一引数にテンプレートファイルのパス、第二引数にパラメータのarrayを入れます。
テンプレートファイルはこんな感じで書けます。
<html>
<body>
<div>{{ name }}</div>
<ul>
{{ for item : items }}
<li>{{ item.name }}</li>
{{ end }}
</ul>
{{ if display }}
<p>foo</p>
{{ else }}
<p>bar</p>
{{ end }}
</body>
</html>
実装方法
基本的にASTいじりで、Lexerでトークナイズしてパーサーでツリー作ってVisitorパターンでevaluateしてPHPファイルを生成します。 Lexer, Parserは手書きです。
上のテンプレートファイルだとこういうPHPファイルになります。
<?php
echo <<<EOS
<html>
<body>
<div>
EOS;
echo $name;
echo <<<EOS
</div>
<ul>
EOS;
foreach ($items as $item) {
echo <<<EOS
<li>
EOS;
echo $item->getName();echo <<<EOS
</li>
EOS;
}
echo <<<EOS
</ul>
EOS;
if ($display) {
echo <<<EOS
<p>foo</p>
EOS;
} else {
echo <<<EOS
<p>bar</p>
EOS;
}
echo <<<EOS
</body>
</html>
EOS;
所感
どういう仕組みでテンプレートエンジンが動いているのかを実際に実装することで体験できたのは良かったです。
ASTの評価プロセスは、基本的には文字列を出力するだけなので言語作るよりかは楽だったw