Twig と Smarty、PHPテンプレートエンジンの選び方を考える
概要
PHP でビューを組み立てるとき、生の PHP を埋め込む方式のほかに、専用のテンプレートエンジンを使う選択肢があります。代表的なのが Twig と Smarty です。どちらも「ロジックとビューを分離する」という同じ目的を持ちながら、設計思想・記法・実行モデルにはっきりした違いがあります。
この記事では、公開情報に基づいて両者の特徴を整理し、「新規なら Twig、既存資産があるなら Smarty」という結論に至るまでの判断軸を考察します。
なぜテンプレートエンジンを使うのか
生 PHP でもビューは書けますが、専用エンジンを挟む理由は主に3つあります。
- ロジックとビューの分離 — テンプレート内でできることを制限し、責務を明確にする
- 安全な出力 — 自動エスケープなどで XSS を防ぎやすくする
- 再利用性 — 継承・インクルード・ブロックでレイアウトを共通化する
Twig と Smarty はどちらもこの目的を満たしますが、力点が違います。
設計思想の違い
Twig : 安全なデフォルトと制限された表現力
- 出力の自動エスケープがデフォルトで有効
- テンプレート内のロジックを意図的に制限し、ロジックの混入を防ぐ
- サンドボックス機能でユーザー提供テンプレートを安全に実行できる
- Symfony の標準テンプレートエンジンであり、単体でも利用可能
Smarty : 柔軟さと歴史ある資産
- 長い歴史と豊富な採用実績(特にレガシー PHP プロジェクト)
- 成熟したプラグイン機構で独自の修飾子・関数を追加しやすい
- 組み込みの出力キャッシュ機構
{$var}系の、PHP 経験者に馴染みやすい記法
記法の比較
変数出力とエスケープ
{# Twig: デフォルトで自動エスケープされる #}
<p>{{ user.name }}</p>
<p>{{ content|raw }}</p> {# 明示的にエスケープを外す #}
<p>{{ title|upper|trim }}</p> {# フィルタのチェーン #}
{* Smarty: 修飾子で明示するのが基本 *}
<p>{$user.name|escape}</p>
<p>{$title|upper|trim}</p>
ここで重要なのがエスケープの扱いです。Twig は「デフォルトで安全、必要なときだけ外す」。Smarty は「必要な箇所で明示的にエスケープする」(設定で有効化することも可能)。XSS 対策の初期安全度では Twig に分があります。
制御構文
{% for item in items %}
<li>{{ item.label }}</li>
{% else %}
<li>データがありません</li>
{% endfor %}
{foreach $items as $item}
<li>{$item.label}</li>
{foreachelse}
<li>データがありません</li>
{/foreach}
テンプレート継承
{# base.html.twig #}
<html>
<body>{% block content %}{% endblock %}</body>
</html>
{# page.html.twig #}
{% extends "base.html.twig" %}
{% block content %}<h1>ページ内容</h1>{% endblock %}
Smarty も 3.x 以降で {extends} / {block} による継承に対応しています。
拡張性の比較
Twig(Extension クラス):
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class AppExtension extends AbstractExtension
{
public function getFilters(): array
{
return [new TwigFilter('yen', fn(int $v) => '¥' . number_format($v))];
}
}
Smarty(プラグイン登録):
$smarty->registerPlugin('modifier', 'yen', fn(int $v) => '¥' . number_format($v));
どちらも十分な拡張性を備えますが、Twig は Extension という体系と Symfony の DI との親和性が特徴です。
パフォーマンスとキャッシュ
両者ともテンプレートを PHP コードにコンパイルしてキャッシュする方式です。初回のコンパイルコストはありますが、2回目以降はコンパイル済みの PHP が使われるため実行時オーバーヘッドは小さくなります。Smarty は加えて「出力キャッシュ」を組み込みで持ち、レンダリング結果自体をキャッシュできます。
開発時はキャッシュにハマりやすいので、次を押さえておきましょう。
- Twig:
cache => falseまたはauto_reload => true - Smarty:
$smarty->setCaching(false)/ コンパイルは変更検知で再生成
選定の判断軸
| 観点 | Twig | Smarty |
|---|---|---|
| 自動エスケープ | デフォルト有効 | 明示 or 設定で有効化 |
| フレームワーク | Symfony 標準 | 特定FW非依存・レガシー実績 |
| 記法 | 独自({% %} / {{ }}) |
PHP 寄り({$var}) |
| 学習コスト | Symfony 経験者は低い | PHP 経験者は低い |
| 既存資産の活用 | 移行コスト大 | 既存 tpl をそのまま活かせる |
| セキュリティ初期値 | 高い | 運用でカバーが必要 |
注意点
- 既存プロジェクトへの後付け: すでに Smarty で大量のテンプレート資産があるなら、Twig への全面移行は記法変換・検証コストが高くつきます。段階移行が現実的です。
- セキュリティのデフォルト差: Smarty ではエスケープを書き忘れない運用が必要です。テンプレートレビューやリンタで担保する仕組みを併用すると安全です。
- バージョン差: Smarty は 5.x で名前空間対応など近代化が進んでいます。採用バージョンのドキュメントを必ず確認してください。
まとめ
- 新規・Symfony 系・安全なデフォルトを重視 → Twig
- 既存の Smarty 資産がある・PHP に近い書き味・移行コスト回避 → Smarty
技術選定は「どちらが優れているか」ではなく「今の制約に合うか」で決めるのが定石です。自動エスケープの初期安全度と Symfony エコシステムの後押しで、新規なら Twig を第一候補に。ただし既存資産を軽視した移行は割に合わないことが多く、そこは冷静に見極めたいところです。
