【WordPress】カテゴリーごとに異なるカスタム投稿テンプレートを動的に切り替える方法

【WordPress】カテゴリーごとに異なるカスタム投稿テンプレートを動的に切り替える方法 WordPress

WordPressでは、投稿タイプやページによってテンプレートファイルを分けることができますが、さらに「投稿に属するカテゴリー」に応じてテンプレートを切り替えたい場面もあります。たとえば、「ニュース」と「ブログ」でレイアウトを変えたい場合などに有効です。

スポンサーリンク

テンプレート切り替えの基本:single_templateフィルターを使用

カテゴリーごとにテンプレートを切り替えるには、functions.phpに以下のコードを追加します。このコードは、投稿が属するカテゴリーに応じて、該当するテンプレートファイルを動的に読み込みます。

functions.php:カテゴリー別テンプレートの切り替え
function custom_single_template_by_category($template) {
  if (is_single()) {
    global $post;
    $categories = get_the_category($post->ID);
    if (!empty($categories)) {
      $category_slug = $categories[0]->slug; // 名前順で最初のカテゴリーを取得
      $custom_template = locate_template("single-cat-{$category_slug}.php");
      if ($custom_template) {
        return $custom_template;
      }
    }
  }
  return $template;
}
add_filter('single_template', 'custom_single_template_by_category');

テンプレートファイルの命名規則

上記のコードでは、カテゴリーのスラッグをもとにsingle-cat-{スラッグ}.phpを読み込みに行きます。たとえば、以下のようなテンプレートファイルを作成することで、それぞれのカテゴリーに応じた表示が可能になります。

  • single-cat-news.php(newsカテゴリ用)
  • single-cat-blog.php(blogカテゴリ用)

該当するテンプレートファイルが存在しない場合は、通常のsingle.phpが使われます。

複数カテゴリに対応する場合の注意点

投稿が複数のカテゴリーに属している場合、$categories[0]がどのカテゴリーになるかに注意が必要です。

$categories[0]は「IDが若い」カテゴリーではない
get_the_category()が内部で使うWP_Term_Queryorderbyデフォルト値は'term_id'ではなく‘name’(名前順)です(公式リファレンスで確認)。つまり$categories[0]が指すのは「IDが最も若いカテゴリー」ではなく、名前が五十音・アルファベット順で最初に来るカテゴリーです。作成日時やID順で優先カテゴリーを決めたい場合は、以下のように明示的に並べ替えてください。
term_id順に明示的に並べ替える例
$categories = get_the_category($post->ID);
usort($categories, function ($a, $b) {
  return $a->term_id <=> $b->term_id;
});
$category_slug = $categories[0]->slug; // IDが最も若いカテゴリーを取得

複数カテゴリ対応の優先順位をさらに細かく制御したい場合は、foreachを使って特定のスラッグを検索する形に変更することも可能です。

特定のカスタム投稿タイプと組み合わせる場合

カスタム投稿タイプのみに適用したい場合は、条件分岐にget_post_type()を追加してください。

投稿タイプの条件分岐を追加
if (is_single() && get_post_type() === 'your_custom_post_type') {
  // 以下同様の処理
}

よくある質問(FAQ)

Qカテゴリーに応じてsingle.phpのテンプレートを切り替えるには?
Asingle_templateフィルターまたはtemplate_includeフィルターを使い、in_category()でカテゴリーを確認してget_template_part()の引数を変えます。子テーマにsingle-{category-slug}.phpという命名規則はWordPress標準のテンプレート階層に存在しないため、filterで実装する必要があります。
Qカテゴリーに異なるサイドバーやレイアウトを適用するには?
Aテンプレートファイル内でget_the_category()でカテゴリーを確認し、カテゴリーに応じて異なるget_template_part()を呼び出したりCSSクラスを付与したりします。
Q複数カテゴリー記事のテンプレート優先度はどうなりますか?
A複数カテゴリーの場合は自前のロジックで優先カテゴリーを決める必要があります。get_the_category()で取得した配列はデフォルトで名前順に並ぶため、IDや作成順を基準にしたい場合はusort()で明示的に並べ替えてから最初の要素を使いましょう。

まとめ

カテゴリーごとに投稿テンプレートを切り替えることで、同じ投稿タイプでもカテゴリの目的に応じたデザインを適用できます。ニュース、コラム、イベントなどでテンプレートを分けたいケースに非常に便利です。フィルターフックとlocate_template()を使えば、柔軟に管理でき、テーマの可読性も損ないません。複数カテゴリーに属する投稿では、優先カテゴリーの決め方を明示的にコントロールすることを忘れないようにしましょう。