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

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

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

スポンサーリンク

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

カテゴリーごとにテンプレートを切り替えるには、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` が使われます。

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

投稿が複数のカテゴリーに属している場合、この実装では**最初のカテゴリー(IDの若いもの)**が優先されます。複数カテゴリ対応の優先順位を細かく制御したい場合は、`foreach`を使って特定のスラッグを検索する形に変更可能です。

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

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


if (is_single() && get_post_type() === 'your_custom_post_type') {
  // 以下同様の処理
}

よくある質問(FAQ)

Q. カテゴリーに応じてsingle.phpのテンプレートを切り替えるには?
A. single_templateフィルターまたはtemplate_includeフィルターを使い、in_category()でカテゴリーを確認してget_template_part()の引数を変えます。または子テーマにsingle-{category-slug}.phpは存在しないため、filterで実装します。
Q. カテゴリーに異なるサイドバーやレイアウトを適用するには?
A. テンプレートファイル内でget_the_category()でカテゴリーを確認し、カテゴリーに応じて異なるget_template_part()を呼び出したりCSSクラスを付与したりします。
Q. 複数カテゴリー記事のテンプレート優先度はどうなりますか?
A. 複数カテゴリーの場合は自前のロジックで優先カテゴリーを決める必要があります。get_the_category()で取得した配列の最初の要素を優先カテゴリーとして扱う方法が一般的です。

まとめ

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