【WordPressテーマの作り方 第12回】条件分岐とテンプレート階層の裏側ロジックを理解しよう(page.php / single.php 編)

📚 本記事は、WordPressテーマの基礎から実践までを学べるシリーズの【第12回】です。
条件分岐やテンプレート階層は、この先の表示カスタマイズやACF活用にも不可欠な知識です。

WordPressテーマ開発で、避けて通れないのがテンプレート階層・条件分岐タグ・page.php/single.phpの使い分け
page.php と single.php の違いがわからない…という初心者も、この記事でスッキリ整理できます!

目次

✅ 今回のゴール

  • 「page.phpとsingle.phpの違いがあやふや」な状態を卒業できる
  • テンプレート階層を使って「表示切り替え」ができるようになる
  • よく使う条件タグの使い分けが身につく

page.phpとsingle.phpの違いをテンプレート階層とともに解説

WordPressでは、表示するコンテンツの種類に応じて自動的にテンプレートが切り替わります。

  • 固定ページ → page.php
  • 投稿 → single.php
  • カスタム投稿(例:news) → single-news.php(なければ single.php

📘 カスタム投稿にもテンプレート階層は適用されます:

投稿タイプ優先されるテンプレート
newssingle-news.php → single.php
voicesingle-voice.php → single.php
eventsingle-event.php → single.php

投稿タイプが増えても、命名ルールを守れば簡単に対応できます。

💡 補足:テンプレート階層は「優先度順」の仕組み

▼ テンプレート階層の優先順を図解すると、以下のようになります:

page-about.php
└ page-{$id}.php
   └ page.php
     └ singular.php
       └ index.php

👆 上の例では、ページスラッグが about の場合に優先的に page-about.php が使われ、なければ順に下位テンプレートにフォールバックされます。

条件分岐タグの基本

テンプレート内で「どのページか」を判定したいときに使えるのが「条件分岐タグ」です。

条件タグ意味
is_home()ブログのトップ(投稿一覧)
is_front_page()フロントページ
is_page()固定ページ
is_single()投稿(カスタム投稿含む)
is_archive()アーカイブ全般
is_post_type_archive()カスタム投稿のアーカイブ
is_attachment()添付ファイルページ
is_search()検索結果ページ
is_404()404エラーページ
is_category()カテゴリアーカイブ

💡 補足:テンプレートファイル名で分岐したいときは?

is_page_template() を使えば、固定ページに割り当てたテンプレートファイル名で処理を分けられます。

// 固定ページに特定テンプレート(template-contact.php)が割り当てられているかを判定
if (is_page_template('template-contact.php')) {
  // お問い合わせページだけスクリプトを読み込む
}

💡 実案件では「特定ページだけ JavaScript を読み込む」といった使い方も便利です。たとえば:

// お問い合わせページ用のスクリプトを読み込む処理(ページテンプレートに応じて動的に制御)
function enqueue_contact_form_script() {
  if (is_page_template('template-contact.php')) {
    // contact-form.js をフッターで読み込む(依存関係なし、バージョンなし)
    wp_enqueue_script('contact-form', get_template_directory_uri() . '/js/contact-form.js', [], false, true);
  }
}
add_action('wp_enqueue_scripts', 'enqueue_contact_form_script'); // フロント側のスクリプト登録フック

💡補足:テンプレート名は get_page_template_slug() で取得できます。
カスタムテンプレートの条件分岐に便利です。

テーマ内の template-contact.php が対象となります。
複数テンプレートで分岐したい場合は in_array() を使ってもOK!

// 現在の固定ページに割り当てられたテンプレートファイル名を取得
$tpl = get_page_template_slug();

// 「お問い合わせ」や「予約」テンプレートの場合だけ処理を実行
if (in_array($tpl, ['template-contact.php', 'template-reserve.php'])) {
  // 特定のテンプレート群だけ処理を分岐
}

🧪 応用:カスタム投稿タイプでレイアウトを切り替える

🔸 template_include でテンプレートを差し替える

条件に応じて読み込むテンプレート自体を動的に変えたいときは、template_include フィルターが便利です。

// カスタム投稿タイプ「voice」の表示時にテンプレートを強制的に切り替える
function switch_template_for_voice($template) {
  if (is_singular('voice')) {
    // テーマ内の single-voice.php を強制的に適用
    return get_template_directory() . '/single-voice.php';
  }
  return $template;
}
add_filter('template_include', 'switch_template_for_voice'); // テンプレート選定フィルター

🎯 たとえば、voice投稿タイプだけまったく違う構成(スライダー付き・吹き出し表示など)にしたい場合に非常に有効です。

このようにして、投稿タイプに応じたテンプレートをPHPで柔軟に制御することも可能です。

📌 この方法は、404ページや検索結果ページのテンプレート変更にも応用できます。

// 404ページだけ独自テンプレートを適用
function custom_404_template($template) {
  if (is_404()) {
    return get_template_directory() . '/custom-404.php';
  }
  return $template;
}
add_filter('template_include', 'custom_404_template');

// 検索結果ページだけテンプレートを変更
function custom_search_template($template) {
  if (is_search()) {
    return get_template_directory() . '/custom-search.php';
  }
  return $template;
}
add_filter('template_include', 'custom_search_template');

テーマごとに個別テンプレートを差し込みたいときにとても便利です。

<?php if (is_singular('news')) : ?>
  <!-- template-parts/single-news.php を読み込む(テンプレートパーツの再利用に便利) -->
  <?php get_template_part('template-parts/single', 'news'); ?>
<?php else : ?>
  <?php get_template_part('template-parts/single', 'default'); ?>
<?php endif; ?>

再利用可能なテンプレートパーツに分けておくと、他の投稿タイプやページでも同じ表示を使い回せるようになります。
これで「news投稿だけ違う見た目にする」といった柔軟な制御が可能になります。

💡 get_template_part() を使う際は、template-parts/single-news.php のように命名規則を決めておくと、整理しやすく再利用にも便利です。

また、存在確認しながらテンプレートを読み込みたい場合は、locate_template() を使う方法もあります。

// 子テーマ → 親テーマの順でテンプレートファイルの存在を確認して取得
$template = locate_template('template-parts/single-voice.php');

if ($template) {
  // テンプレートが存在する場合は読み込む
  include $template;
} else {
  // 存在しない場合はデフォルトテンプレートを読み込む
  include get_template_directory() . '/template-parts/single-default.php';
}

💡 locate_template() は、子テーマ→親テーマの順にテンプレートを探してくれるため、カスタマイズ性が高くおすすめです。

読み込み順:
子テーマ → 親テーマ → デフォルトテンプレート

【例】
template-parts/single-voice.php(子)
→ template-parts/single-voice.php(親)
→ template-parts/single-default.php(親)

🛠 よくあるミスと対策

is_page() はループ外でも使えるが、ページによっては get_queried_object() の方が確実な場合も。

// 現在表示中の投稿(固定ページ)オブジェクトを取得
$page = get_queried_object();

// スラッグ(post_name)が 'about' のページのみ処理
if ($page->post_name === 'about') {
  // 「会社概要」ページだけ処理を変える
}

is_front_page()is_home() の使い分けに注意!

if (is_front_page()) {
  // 固定ページのトップ
} elseif (is_home()) {
  // 投稿一覧(ブログトップ)
}

💡 補足:条件を組み合わせたいときは?

if (is_single() && has_category('news')) {
  // 「投稿」で、かつ「newsカテゴリ」なら
}

&&(かつ)や ||(または)で自由に条件を組み合わせましょう!

📝 まとめ

  • page.php は固定ページ用、single.php は投稿用テンプレート
  • テンプレート階層を理解すると、表示制御の自由度が大幅に上がる
  • 条件分岐タグでページごとの処理を出し分けよう!

ちなみに、カスタム投稿や条件分岐を極めていくと、投稿ごとに違う情報を出し分ける場面も増えてきます。
そこで重要になるのが「カスタムフィールド」。

🧩 本記事で登場した主な関数・条件タグ:
get_template_part(), locate_template(), template_include, is_page(), is_single(), is_page_template(), get_page_template_slug(), is_404(), is_search() など

🚫 ちなみに、single.phpやpage.phpに条件を直接ベタ書きしすぎると、管理しにくくなりがちです。テンプレートパーツや階層構造をうまく活用して保守性を高めましょう。

🔮 次回予告

第13回では、投稿ページでのメタ情報の表示やカスタムフィールドの活用術を紹介予定です。
クライアント案件でもよくある「詳細ページのカスタマイズ」に踏み込みます!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Web制作会社勤務、業界歴10年以上。現場を走り回ってきた制作者。
これからWeb制作を学ぶ人に寄り添いながら、実務で役立つ知識をわかりやすくシェアします。
「ゼロぐらいから学べる!」をモットーに、あなたの“がんばろ”を応援します!

目次