2019-06-09

PHPのテンプレートエンジンを自作してみた

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

このエントリーをはてなブックマークに追加