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() の移し忘れ、キャッシュ、ライブラリの衝突を導入直後に確認する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲