【WordPress】カスタム投稿タイプごとに異なるテンプレートを適用する方法

【WordPress】カスタム投稿タイプごとに異なるテンプレートを適用する方法 WordPress

WordPressでは、カスタム投稿タイプ(CPT)を使うことで、投稿とは異なる独自のコンテンツ構造を作成できます。しかし、投稿タイプに応じてテンプレートを出し分けたい場合は、それに応じたファイル設計が必要です。

この記事では、カスタム投稿タイプごとにテンプレートを分ける方法を、基本から応用まで解説します。

スポンサーリンク

基本:テンプレート階層のルールを理解する

WordPressにはテンプレート階層という仕組みがあり、カスタム投稿タイプの場合も次のような順番でテンプレートが読み込まれます。

例:投稿タイプが movie の場合

表示画面 優先されるテンプレートファイル
一覧ページ archive-movie.phparchive.phpindex.php
詳細ページ single-movie.phpsingle.phpsingular.phpindex.php

これらのルールに従い、テンプレートファイルを命名するだけで自動的に適用されます。

カスタム投稿タイプの一覧ページにテンプレートを適用する

たとえば、bookという投稿タイプを登録している場合

テーマディレクトリに作成
// テーマディレクトリに以下のファイルを作成
archive-book.php

このファイルにHTMLやループを記述すれば、https://example.com/book/ にアクセスした際にこのテンプレートが読み込まれます。

has_archiveがtrueでないとアーカイブページ自体が存在しない
archive-book.phpを用意しても、register_post_type()'has_archive' => trueを設定していなければ、アーカイブページのURL自体が生成されず/book/は404になります。カスタム投稿タイプを登録する際はhas_archiveを有効にし、パーマリンク設定を保存してリライトルールを更新しておいてください。

詳細ページ用テンプレートの適用

個別の投稿ページ(シングルページ)には、single-投稿タイプ名.php を使います。

投稿タイプ「event」の詳細ページテンプレート
// 例:投稿タイプ「event」の詳細ページテンプレート
single-event.php

これにより、各イベントの詳細表示に専用のテンプレートが適用されます。

すべてのカスタム投稿タイプを1ファイルで処理したい場合

複数のカスタム投稿タイプを一括で処理したい場合は、singular.php や archive.php を使って共通テンプレートを作成する方法もあります。

ただし、投稿タイプの分岐処理が必要になるため、以下のように条件分岐を使います。

singular.php:投稿タイプごとにレイアウトを分岐
<?php
$post_type = get_post_type();

if ($post_type === 'book') {
  // book用のレイアウト
} elseif ($post_type === 'event') {
  // event用のレイアウト
} else {
  // デフォルト
}
?>

functions.php でテンプレートを動的に指定する(上級者向け)

NG:子テーマ環境ではテンプレートが見つからない
function my_custom_template_include($template) {
  if (is_singular('movie')) {
    return get_template_directory() . '/single-movie.php';
  }

  return $template;
}
add_filter('template_include', 'my_custom_template_include');
// 子テーマにsingle-movie.phpを置いても、親テーマ側のパスを返してしまう
get_template_directory() は親テーマのパスを返す
get_template_directory()親テーマのディレクトリパスを返す関数です。子テーマ側にsingle-movie.phpを置いても、このコードは親テーマ内の存在しないパスを返してしまい、file_exists()のチェックも無いため読み込みに失敗します。子テーマ・親テーマの両方を検索し、見つからなければ空文字を返すlocate_template()を使うのが安全です。
OK:locate_template()で子テーマにも対応
function my_custom_template_include($template) {
  if (is_singular('movie')) {
    // 子テーマ→親テーマの順で探し、見つからなければ空文字を返す
    $custom_template = locate_template('single-movie.php');
    if ($custom_template) {
      return $custom_template;
    }
  }

  return $template;
}
add_filter('template_include', 'my_custom_template_include');

この方法は、テンプレートファイルの柔軟な切り替えに便利です。

よくある質問(FAQ)

Qカスタム投稿タイプのテンプレートファイルの命名規則は?
Asingle-{post_type}.phpがシングルページのテンプレートです。archive-{post_type}.phpがアーカイブページです。テーマのテンプレート階層に従いWordPressが自動で適切なテンプレートを選択します。
Q子テーマにカスタム投稿タイプのテンプレートを追加するには?
A子テーマのルートディレクトリにsingle-custom_type.phpを作成するだけで、親テーマのテンプレートに優先して使用されます。
Qtemplate_includeフィルターを使って動的にテンプレートを切り替えるには?
Aadd_filter(‘template_include’, function($template){ if(is_singular(‘custom_type’)){ $new = locate_template(‘my-template.php’); if($new){ return $new; } } return $template; })と実装します。

まとめ

カスタム投稿タイプを導入するだけでなく、それぞれに合ったテンプレートを適用することはユーザー体験の向上につながります。

テンプレート階層を理解し、archive-○○.php や single-○○.php を正しく使うことで、簡潔かつメンテナンスしやすい構成が実現できます。動的にテンプレートを切り替える場合は、子テーマ環境でも確実に見つかるlocate_template()を使いましょう。

投稿タイプの設計段階からテンプレート分離を意識しておくと、テーマ開発や運用がよりスムーズになります。