WordPressのテンプレートファイルには「使ってはいけない」という声がある一方で、実際の制作現場ではなくてはならない機能でもあります。この記事では、テンプレートファイルの仕組みを整理した上で、正当な活用パターンと、ブロックテーマでは難しいケースについて解説します。


    そもそも「コンテンツをテンプレートファイルに書く」とはどういうことか

    テンプレートファイルを巡る議論の多くは、「どう使っているか」を混同したまま行われています。まず状況を整理します。

    問題になるパターン(コンテンツの直書き)

    // page-about.php
    // ❌ 会社概要の文章や画像パスをPHPに直書き
    ?>
    <h1>株式会社〇〇について</h1>
    <p>私たちは1990年創業の...</p>
    <img src="/wp-content/themes/mytheme/img/about.jpg" alt="">
    

    このパターンの問題は明確で、テキスト1文字を直すだけでもファイル編集が必要になり、WordPressの管理画面から更新できなくなります。HTMLを読める人でないと触れないため、クライアントへの引き渡しが困難になります。

    正当なパターン(骨格の定義)

    // page/page-about.php(カスタムページテンプレート)
    // ✅ コンテンツはDBから、テンプレートはレイアウト制御のみ
    <?php get_header(); ?>
    <div class="trunker trunker-about mx-auto">
      <aside class="flanker"><?php dynamic_sidebar('sidebar-about'); ?></aside>
      <main class="main">
        <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
          <div class="post-content"><?php the_content(); ?></div>
        <?php endwhile; endif; ?>
      </main>
    </div>
    <?php get_footer(); ?>
    

    コンテンツは the_content() でデータベースから取得しています。テンプレートは「どのレイアウトで表示するか」だけを担っています。これはWordPressの設計思想に則った正しい使い方です。


    テンプレートファイルの基本:2種類の仕組み

    WordPressには、ページにテンプレートを適用する方法が2種類あります。混同しやすいので整理しておきます。

    ① テンプレート階層(スラッグ・IDによる自動適用)

    ファイル名にスラッグやIDを含めると、該当ページに自動でテンプレートが適用されます。

    page-{slug}.php   → スラッグが一致する固定ページに自動適用
    page-{id}.php     → IDが一致する固定ページに自動適用
    single-{post-type}.php → カスタム投稿タイプに自動適用
    

    例えば page-contact.php というファイルを作ると、スラッグが contact の固定ページにだけこのテンプレートが自動的に使われます。管理画面で選ぶ操作は不要です。

    ② カスタムページテンプレート(手動選択)

    PHPファイルの先頭に Template Name: コメントを書くと、管理画面の固定ページ編集画面に選択肢として表示されます。

    <?php
    /**
     * Template Name: LP用(ヘッダー・フッターなし)
     * Template Post Type: page, post
     */
    ?>
    

    Template Post Type を指定すると、固定ページ以外にも選択肢を表示できます。上記の例では固定ページと投稿ページの両方の編集画面に選択肢が出ます。

    ファイルの置き場所は自由です。WordPressはテーマディレクトリ内を再帰的にスキャンして Template Name: を探すので、templates/page/page-templates/ など、どこに置いても機能します。各テーマのディレクトリ構成を参考にすると templates/ に置くパターンが多いです。

    ① と ② の使い分け

    テンプレート階層(自動) カスタムページテンプレート(手動)
    適用方法 スラッグ・IDで自動 管理画面で手動選択
    ファイル名規則 あり(page-{slug}.php 任意
    複数ページへの再利用 不可(1ページ専用) 可能
    向いている用途 ページ固有の特殊処理 汎用レイアウト切り替え

    テンプレートファイルの正当な活用パターン

    パターン1:レイアウトの切り替え

    最もよく使われる用途です。同じコンテンツでも、ページによってサイドバーの有無やカラム構成を変えたい場合に使います。

    // templates/one-column.php
    /**
     * Template Name: 1カラム(サイドバーなし)
     * Template Post Type: post, page
     */
    get_template_part( 'page' ); // 既存のpage.phpに処理を委譲するだけ
    

    Arkheテーマはこのパターンを採用していて、テンプレートファイルが実質2行で完結しています。「テンプレートファイルはルーティングだけを担う」という設計の好例です。

    LP(ランディングページ)ではヘッダーとフッターを省略したいケースもあります。

    // templates/blank.php
    /**
     * Template Name: LPレイアウト(ヘッダー・フッターなし)
     * Template Post Type: page
     */
    // ヘッダー・フッターを呼ばない = get_header(), get_footer() を書かない
    the_content();
    

    パターン2:ページ種別ごとのCSS・JS分岐

    head.phpfunctions.php 内で、適用されているテンプレートを判定してアセットを切り替えます。

    // head.php(抜粋)
    <?php if (is_page_template('page/page-equipment.php')) : ?>
      <!-- 設備ページ専用CSS -->
      <link rel="stylesheet" href="<?php theme_file('/css/pg-equipment.css'); ?>" />
    
    <?php elseif (is_page_template('page/page-plan.php')) : ?>
      <!-- プランページ専用CSS -->
      <link rel="stylesheet" href="<?php theme_file('/css/pg-plan.css'); ?>" />
    <?php endif; ?>
    

    wp_enqueue_style() でも同様の制御は可能ですが、is_page_template() の使いどころや読み込み順を細かく制御したい場合は直書きの方がシンプルに書けます。

    パターン3:特定テンプレートだけフィルターを外す

    あるテンプレートが適用されているときだけ、グローバルに設定されているフィルターを無効化するパターンです。

    // page/page-converter.php
    /**
     * Template Name: コンバーターツール用
     */
    
    // このテンプレートでのみ、パス置換フィルターを無効化
    remove_filter('the_content', 'replace_media_paths');
    remove_filter('the_content', 'add_version_query_to_images');
    

    functions.php 側に条件分岐を書くこともできますが、テンプレートファイルの先頭に書いた方が「このページではこう動く」という意図がひと目で分かります。

    パターン4:共通パーツとしてのinclude

    pageband-elf.php(ページ帯)や breadcrumb.php(パンくずリスト)のような共通パーツを、テンプレートファイルから include して使います。

    // page.php 内
    <header class="post-header">
      <?php get_template_part('parts/pagecover/pageband-elf'); ?>
      <?php get_template_part('parts/breadcrumb/breadcrumb'); ?>
    </header>
    

    これは「コンテンツをテンプレートに書く」とは根本的に異なります。パーツファイル自体は動的に内容を切り替えており、コンテンツはDBから取得しています。


    比較:テンプレートファイルの使い方による違い

    「テンプレートにコンテンツを書く(NG)」と「テンプレートを骨格として使う(OK)」の実際の差を整理します。

    項目 NG:テンプレートにコンテンツを書く OK:テンプレートは骨格のみ
    作成方法 page-about.php にHTMLを直書き 固定ページで作成、テンプレートを選択
    編集環境 ファイルエディター or FTP 管理画面のブロックエディター
    必要スキル HTML/PHP必須 不要(管理画面で操作)
    レイアウト柔軟性 高い(コードで何でも書ける) ブロックの範囲内
    クライアント更新 困難(コード編集が必要) 容易(ボタン操作で更新)
    リビジョン なし(バックアップが必要) あり(管理画面で履歴管理)
    保守性 ページ増加でファイルが増殖 固定ページ一覧で一元管理
    再利用性 1ファイル=1ページ専用 1テンプレート=複数ページで使い回し可

    「更新のしやすさ」と「リビジョン」が最も差が出るポイントです。テンプレートにコンテンツを書くと、文字1文字の修正でもファイル操作が必要になります。一方でテンプレートを骨格として使えば、コンテンツの管理は固定ページで行えるため、クライアント自身が更新できる状態を保てます。

    なお「保守性」については、templates/page-XXX.php が10個ある場合と、固定ページが10個ある場合で管理の手間に大きな差はありません。骨格としてのテンプレートファイルが増えること自体は問題ではなく、各ファイルにコンテンツが混入することが問題です。


    ブロックテーマでは難しいパターン

    WordPress 5.9以降、ブロックテーマ(FSE:フルサイト編集)が推進されており、テンプレートのカスタマイズも管理画面上で行えるようになっています。ただし、主要な案件でブロックテーマが最適かというと、現時点では難しいケースが存在します。以下では、実際のWebサイトのレイアウトを例に、どこが技術的な障壁になるかを具体的に見ていきます。


    ケース1:左固定サイドバー+独立したスクロール領域

    REVENGE POP - メインビジュアル
    REVENGE POP - コンテンツページ

    上記のようなサイトでは、左端に「REVENGE POP」という縦書きテキストが position: fixed で画面に固定されたまま、右側のコンテンツ領域だけが独立してスクロールする構造になっています。

    ブロックテーマでこのレイアウトを実現しようとすると、次の点で壁にぶつかります。

    position: fixed サイドバーのコンテナ問題
    ブロックテーマのサイトエディターで生成されるテンプレートは、<div class="wp-site-blocks"> というルートコンテナの中に主要な要素が収まります。position: fixed の要素はビューポート基準で配置されますが、このコンテナ構造の中で意図通りに機能させるには、テーマが生成するCSSを上書きする必要があり、theme.jsonspacinglayout 設定と競合が起きやすくなります。

    スクロール領域の分離
    左サイドバーを固定したまま右側だけをスクロールさせるには、コンテンツ領域に overflow-y: scroll; height: 100vh; を当てる必要があります。しかしブロックの GroupCover ブロックはデフォルトで overflow: hidden を持ち、かつブロックギャップやパディング設定が干渉するため、カスタムCSSで打ち消す箇所が多くなります。実質的にカスタムHTMLブロックで全体を書くことになり、ブロックテーマを使うメリットが薄れます。


    ケース2:縦書きテキスト+写真の自由配置

    十木舎 - トップページ
    十木舎 - コンセプトページ
    十木舎 - コンテンツ詳細
    十木舎 - 作品ページ

    縦書き(writing-mode: vertical-rl)で組まれた日本語テキストと、ページ上に散らばるように絶対配置された複数の写真が重なり合うレイアウトです。

    縦書きテキストブロックが存在しない
    コアブロックに writing-mode を設定できるものはありません。「段落」ブロックや「見出し」ブロックに追加CSSクラスを当てて writing-mode: vertical-rl を適用することは可能ですが、縦書きにした際の行間・字間・フォントサイズのレスポンシブ調整をブロックエディターのUIから行うことはできず、すべてCSSで記述する必要があります。また clamp() を使った流体サイズ指定も、ブロックの「タイポグラフィ」設定には対応していないため手書きになります。

    写真の自由配置と重なり
    ブロックエディターの基本構造はドキュメントフロー(上から下に積み重なる)です。写真を任意の座標に絶対配置し、テキストや他の要素と重ねるには position: absolutetop/left 値の指定が必要ですが、これをブロックエディターのUIで行う方法はありません。カスタムHTMLブロックを使うか、専用のカスタムブロックを開発する必要があり、いずれも「管理画面で触れるブロックテーマ」の利点が失われます。


    ケース3:非均等マルチカラムの実績一覧

    DRAFT - 実績一覧
    DRAFT - 実績詳細

    各カードのサイズが不均等で、異なる縦横比の画像がCSS Gridの grid-column スパン指定によって配置されているレイアウトです。ホバー時に案件情報がオーバーレイで表示される動作も組み合わさっています。

    均等グリッドしか持たない Galleryブロック
    Gallery ブロックは主要なアイテムを均等なグリッドで表示します。各アイテムに異なる grid-column: span 2grid-row: span 2 を与えることはUIからは不可能です。カスタム投稿タイプで実績データを管理し、クエリループブロックで一覧表示するアプローチが最も近い実装になりますが、その場合でも各カードへの個別グリッドスパン指定はPHPかJSで動的に出力するしかありません。

    ホバーインタラクションの実装
    カード上にオーバーレイ表示するインタラクションはCSS(:hover + opacitytransform)で実装しますが、ブロックエディター上では確認できず、実装・調整はすべてCSSファイル編集になります。クラシックテーマなら is_page_template() でこのページにだけJSとCSSを読み込む制御が容易ですが、ブロックテーマでは wp_enqueue_scripts フックで is_page_template() の判定タイミングに注意が必要です。


    ケース4:ブリード配置+テキストとビジュアルの混在

    造園 - コンセプト
    造園 - サービス

    コンテンツ幅(max-width で制限されたテキスト)と全幅(ビューポート端まで伸びる画像)が混在し、さらに画像の角にアクセントカラーの矩形が絶対配置で重なっているレイアウトです。

    ブリード(全幅)とコンテンツ幅の混在制御
    ブロックテーマは theme.jsoncontentSize(コンテンツ幅)と wideSize(ワイド幅)を定義し、ブロックの「幅」設定でこれを切り替えます。しかしこのシステムは「全幅」か「コンテンツ幅」かの二択に近く、セクションごとに異なる max-width を使い分けたり、特定の要素だけ calc(50% + 50vw) のようなトリックで片側だけブリードさせたりするパターンは、theme.json の設定と干渉します。クラシックテーマなら各セクションのCSSを自由に記述できるため、こうした複合的な幅制御は容易です。

    絶対配置の装飾要素
    画像の右下や左下に重なる蛍光色の矩形は position: absolute で配置されています。Cover ブロックや Group ブロックに position: relative を持たせて子要素を絶対配置することは一応可能ですが、レスポンシブでの位置調整(bottom: 0; right: -20px のような指定)はブロックエディターのUIでは扱えず、テーマCSSの記述が必要です。ブロックテーマの場合、こうしたCSSは theme.json または style.css に書くことになりますが、ブロックが生成するHTMLの構造に依存するため、アップデートで崩れるリスクがあります。


    ブロックテーマで十分対応できるケース

    一方で、次のような用途はブロックテーマのサイトエディターで問題なく実現できます。

    • サイドバーの有無の切り替え、カラム数の変更
    • LP用のヘッダー・フッターなしレイアウト
    • コンテンツ幅内に収まる標準的なページデザイン
    • テキスト・画像・ボタンの配置と色調整

    Snow Monkeyは「静的ビューテンプレート機能」(/templates/static/ にURLに対応したファイルを置く仕組み)を提供しており、クラシックテーマのページテンプレートが担っていた「URL単位でビューを切り替える」役割をブロックテーマの文脈で再実装しています。こうしたアプローチはブロックテーマの制約を補完するものとして参考になります。

    PHPによる条件分岐や動的な処理が必要な場面では、ブロックテーマのHTMLテンプレートからダイナミックブロックを経由することになり、クラシックテーマのPHPテンプレートに比べて実装コストが上がる傾向があります。案件の要件を整理した上でテーマの選択を判断することが重要です。


    まとめ

    テンプレートファイルの使い方を整理すると次のようになります。

    テンプレートファイルが適している用途

    • サイドバーの有無、カラム数など、レイアウト構造の切り替え
    • ページ種別ごとのCSS・JS読み込み制御
    • 特定テンプレート適用時だけのフィルター・フック処理
    • 共通パーツ(ページ帯、パンくず)のinclude

    テンプレートファイルに書いてはいけないもの

    • ページ固有のテキストコンテンツ(会社概要の文章など)
    • 直接パスを指定した画像(メディアライブラリ経由で管理すべきもの)
    • クライアントが定期的に更新する情報

    テンプレートファイルは「どう表示するか(構造)」を担い、「何を表示するか(コンテンツ)」はデータベース(固定ページ・投稿)で管理する。この分離が守られている限り、templates/page-contact.phptemplates/page-equipment.php が存在することは何ら問題ありません。

    ブロックテーマへの移行は今後も進んでいきますが、複雑なレイアウト要件や高い移植性が求められる案件では、クラシックテーマのPHPテンプレートが依然として合理的な選択肢です。どちらが優れているかではなく、案件の要件に応じて使い分けることが重要です。