2026年8月16日
2026年8月16日
WordPressテーマにTwig・Blade・Mustacheを統合する方法と選び方
WordPress のテーマで Twig を使うなら Timber、Blade を使うなら Roots の Sage(Acorn)を土台にするのが、2026年10月現在もっとも情報が多く保守されている方法です。Mustache は PHP と JavaScript で同じテンプレートを共有したい場面に向いています。この記事では、3つのエンジンの違いと選び方、Composer での導入から最初のテンプレートを表示するまでの手順、エスケープやキャッシュなど統合時につまずく点を説明します。
テンプレートエンジンを使う理由と、使わないほうがよい場面
WordPress の標準的なテーマは PHP ファイルに HTML とロジックを混ぜて書きます。テンプレートエンジンを入れると、データを用意する PHP と表示を担当するテンプレートを分けられ、レイアウトの継承や部品化がしやすくなります。デザイナーとの分業や、大きなクラシックテーマの保守で効果が出やすい方法です。
一方で、ブロックテーマ(フルサイト編集)では、テンプレートは templates/ 配下の HTML とブロックマークアップで構成され、サイトエディターから編集されます。ここに Twig や Blade は入り込みません。ブロックテーマを作る場合は、エンジンを使うのはブロックのサーバー側レンダリングなど一部に限られます。また WooCommerce のように PHP のテンプレート上書きを前提にしているプラグインと組み合わせると、そのプラグイン部分は PHP のまま残ることも理解しておきます。
3つのエンジンの違い
| 項目 | Twig(Timber) | Blade(Sage / Acorn) | Mustache |
|---|---|---|---|
| WordPress 向けの土台 | Timber | Roots の Sage・Acorn | 汎用ライブラリを自分で接続 |
| 書き方の特徴 | 継承・ブロック・フィルター | Laravel と同じ構文、ディレクティブ | ロジックを持たない最小構文 |
| 出力のエスケープ | 設定で自動エスケープを有効化 | {{ }} はエスケープ、{!! !!} は生出力 |
{{ }} はエスケープ、{{{ }}} は生出力 |
| 向いている場面 | クラシックテーマ全体の置き換え | Laravel 経験者のチーム、ビルド工程込みの開発 | PHP と JS で同じテンプレートを使う部品 |
どれも Composer で PHP ライブラリを読み込む構成になります。ホスティング先で Composer を実行できない場合は、手元でインストールした vendor/ ディレクトリをデプロイに含める運用を決めておきます。
Twig を Timber で統合する手順
Timber はバージョン2から Composer での導入が基本になりました。以前のように WordPress.org のプラグインとして入れる方法は案内されなくなっているため、新規に始めるなら Composer を前提にしてください。作業はステージング環境で、テーマのバックアップを取ってから行います。
cd wp-content/themes/my-theme
composer require timber/timber
functions.php でオートローダーを読み込み、Timber を初期化します。
<?php
// my-theme/functions.php
require_once __DIR__ . '/vendor/autoload.php';
Timber\Timber::init();
// Twig ファイルを置くディレクトリ
Timber\Timber::$dirname = array( 'views' );
テンプレート階層はそのまま使えます。たとえば single.php では、テンプレートに渡すデータを用意して Twig ファイルを描画します。
<?php
// my-theme/single.php
$context = Timber\Timber::context();
$context['post'] = Timber\Timber::get_post();
Timber\Timber::render( 'single.twig', $context );
{# views/single.twig #}
{% extends "base.twig" %}
{% block content %}
<article>
<h1>{{ post.title|e('html') }}</h1>
<a href="{{ post.link|e('html_attr') }}">{{ post.title|e('html') }}</a>
{{ post.content|raw }}
</article>
{% endblock %}
base.twig に {% block content %}{% endblock %} を含む共通レイアウトを書き、wp_head() と wp_footer() に相当する出力を入れておきます。Timber のスターターテーマを参考にすると、これらの置き場所が分かりやすいです。
エスケープの設定
Twig は自動エスケープを設定で切り替えられ、Timber での既定値はバージョンによって異なることがあります。テンプレートごとに |e('html') や |e('html_attr') を付けるか、自動エスケープを有効にして全体を守るかを、チームで最初に決めておきます。自動エスケープを有効にした場合、本文のように意図的に HTML を出す値には |raw が必要になります。|raw を付けるのは、the_content フィルターを通った本文のように WordPress 側で処理済みの値に限り、フォーム入力やクエリ文字列由来の値には付けないでください。
Blade を Sage / Acorn で統合する手順
Blade を使いたい場合、Roots が開発している Sage テーマを土台にするのが現実的です。Sage は Acorn というパッケージを通じて Laravel の Blade やサービスコンテナを WordPress に持ち込みます。Composer に加えて Node.js のビルド工程も含むため、導入手順は公式ドキュメントのバージョンに合わせて進めてください。
Blade の構文は Laravel と同じです。
{{-- resources/views/partials/content-single.blade.php --}}
<article @php(post_class())>
<h1>{{ get_the_title() }}</h1>
<div class="entry-content">
@php(the_content())
</div>
</article>
{{ }} の中身は htmlspecialchars でエスケープされます。生の HTML を出す {!! !!} は、wp_kses_post() を通した値など安全が確認できるものだけに使います。Blade はテンプレートを PHP にコンパイルしてキャッシュするため、キャッシュ用ディレクトリに書き込み権限が必要です。本番デプロイ後に表示が古いままのときは、まずこのキャッシュを疑います。
既存テーマに Blade だけを後付けするライブラリもありますが、保守が止まっているものも見られます。採用する前にリポジトリの更新状況と、対応している PHP のバージョンを確認してください。
Mustache を部品単位で使う方法
Mustache はロジックを持たない構文で、PHP 版(mustache/mustache)と JavaScript 版が同じテンプレートを解釈できます。たとえば「最初の表示は PHP で出し、絞り込み後の再描画は JavaScript で行う」カードの一覧のように、同じ見た目を両方で作る部品に向いています。
composer require mustache/mustache
<?php
require_once __DIR__ . '/vendor/autoload.php';
function myprefix_render_card( array $data ) {
$engine = new Mustache_Engine( array(
'loader' => new Mustache_Loader_FilesystemLoader( __DIR__ . '/templates' ),
) );
return $engine->render( 'card', $data );
}
echo myprefix_render_card( array(
'title' => get_the_title(),
'url' => get_permalink(),
) );
{{! templates/card.mustache }}
<article class="card">
<a href="{{url}}">{{title}}</a>
</article>
{{ }} は HTML エスケープされますが、URL として安全かどうかまでは見ません。PHP 側で esc_url() を通してから渡すのが安全です。なお WordPress コアの管理画面には wp.template() という Underscore ベースの JS テンプレートがあり、{{ }} がエスケープ、{{{ }}} が生出力という似た書き方をします。管理画面だけで使う部品なら、外部ライブラリを足さずにこちらで足りることもあります。
統合時につまずきやすい点
- ライブラリのバージョン衝突: 別のプラグインが異なるバージョンの Twig などを同梱していると、どちらが先に読み込まれるかで動作が変わります。配布用のプラグインに同梱する場合は、名前空間を書き換えるツール(Strauss や PHP-Scoper など)の利用を検討します
- キャッシュの扱い: Twig も Blade もコンパイル結果をキャッシュできます。開発中はキャッシュを切り、本番では有効にして、デプロイ時に消す手順を決めておきます
- フックが動かない:
wp_head()、wp_footer()、body_class()などをテンプレートに移し忘れると、プラグインのスクリプトや管理バーが表示されません。最初にこれらが出力されているかを確認します - 子テーマとの関係: 親テーマがエンジンを使っている場合、子テーマで上書きするのは PHP ファイルではなく Twig や Blade のファイルになります。上書きの探索順序はエンジンの設定に依存するため、親テーマのドキュメントを確認します
まとめ
- Twig は Timber(Composer で導入)、Blade は Sage / Acorn、Mustache は PHP と JS でテンプレートを共有したい部品に向く
- ブロックテーマのテンプレートには入らないため、主な対象はクラシックテーマやハイブリッド構成
- エスケープの方針を最初に決め、生出力(
|raw・{!! !!}・{{{ }}})は処理済みの値だけにする wp_head()/wp_footer()の移し忘れ、キャッシュ、ライブラリの衝突を導入直後に確認する