子カテゴリのアーカイブページを親カテゴリ用のテンプレートファイルで表示しよう

子カテゴリのアーカイブページを親カテゴリ用のテンプレートファイルで表示しよう - category.phpで振り分けしてもいいんだけどね

説明

少し前に投稿した「適切なテンプレートファイルを用意してテンプレート内の振り分け処理を無くす」で説明した通り、特定のカテゴリ専用のテンプレートとしてcategory-○○.phpを用意することで、category.phpやarchive.php内で振り分けを行う必要がなくなる。ただ、すべてのカテゴリ分を用意するのは効率的ではないし、特に子カテゴリについては親カテゴリと共通内容になるケースが多いのではないだろうか。ここでは、子カテゴリの個別テンプレートファイルを作らず、親カテゴリのテンプレートを利用する方法を紹介する。
カテゴリのテンプレートファイルがない場合の振る舞い

以前の投稿のおさらいを兼ねて、カテゴリのテンプレートファイルがどのように検索されるかを整理する。WordPressのシステムではユーザのリクエストがカテゴリページの場合、次の順番でテーマ内のテンプレートファイルを検索し、最初に見つかったテンプレートファイルを読み込んで、リクエストに応答する。

1.category-slug.php ※slugはカテゴリのスラッグ
2.category-id.php ※idはカテゴリのID
3.category.php
4.archive.php
5.index.php

例えば、'ニュース'というカテゴリのスラッグが'news'でIDが10の場合、WordPressシステムではcategory-news.php → category-10.php → category.php → category.php → index.phpの順で検索し、最初に見つかったテンプレートファイルが適用される。この振る舞いは子カテゴリの場合も同様である。

子カテゴリのテンプレートファイルがない場合は親カテゴリのテンプレートファイルを使う

今回紹介するケースは、複数のカテゴリがあり、その中には親子関係のカテゴリが含まれている。さらに、子カテゴリについてはテーマ提供後に追加される可能性があるとしよう。このようなケースの対応を考えた場合、通常であればcategory.phpかarchive.phpの内部で振り分けることになるだろう(子カテゴリを追加した際に、その子カテゴリ用のテンプレートファイルを追加できるのならそれでもいいのだが……)。

こんな時、子カテゴリの表示内容が親カテゴリの表示内容と大きく違いがないならば、子カテゴリ(さらに孫カテゴリも)の表示については、親カテゴリのテンプレートファイルと共通にして対応できればかなり効率的だろう。つまり、子カテゴリについては専用のテンプレートファイルを作らず、親カテゴリのテンプレートを使うというものだ。

通常、前述の通り子カテゴリのスラッグまたはIDを付与した専用テンプレートファイルがない場合はcategory.php→archive.php→index.phpの何れかが適用さえるのだが、以下のコードをfunctions.phpに記述することで専用テンプレートファイルがない場合に親(さらにその親も)カテゴリのテンプレートファイルが利用可能になる。

add_filter( 'category_template', 'my_category_template' );

function my_category_template( $template ) {
	$category = get_queried_object();
	if ( $category->parent != 0 &&
		( $template == "" || strpos( $template, "category.php" ) !== false ) ) {
		$templates = array();
		while ( $category->parent ) {
			$category = get_category( $category->parent );
			if ( !isset( $category->slug ) ) break;
			$templates[] = "category-{$category->slug}.php";
			$templates[] = "category-{$category->term_id}.php";
		}
		$templates[] = "category.php";
		$template = locate_template( $templates );
	}
	return $template;
}

使用するフィルターは'category_template'。名前でわかる通りリクエストがカテゴリページの場合に対応するテンプレートファイルを選択する際に使用されているフィルターである。このフィルターに対応する関数のパラメータ$templateには、テーマ内にテンプレートファイルがある場合はそのパス名が、なかった場合は''が設定されてくる。普通にテーマを作っているなら、カテゴリの専用テンプレートファイルまたは'category.php'のパス名になるだろう。

上記処理では、リクエストされたカテゴリページのカテゴリが子カテゴリ(親カテゴリを持つ)場合、$templateが専用テンプレートファイルのパス名でない(テンプレートファイルが見つからない、または'category.php'のケース)ならば、親カテゴリのテンプレートがあるかを調べている。また直接の親カテゴリだけでなく、その親カテゴリも調べる対象にしており、よりリクエストされたカテゴリに近い親カテゴリのテンプレートファイルを検索するようにしている。

と、久しぶりにサイト構築でこのようなケースに遭遇したので、事例として紹介しました。フィルター処理中に登場したget_queried_object関数だが、WordPress 3.1.0で提供されたもの。ここではリクエストされたカテゴリ情報を取得しているが、アーカイブページのデータ取得する場合など幅広く使えそうだ。

関連

お勧めコンテンツ

register_widget(2011年7月22日 登録)

void register_widget( string $widget_class )
ウィジェットを登録する。

get_the_date(2011年4月13日 登録)

mixed get_the_date ( [ string $d = '' [ , mixed $post = null ] ] )
パラメータ$dで指定したフォーマットで投稿日を取得する。

delete_term_meta(2016年2月23日 登録)

bool delete_term_meta( int $term_id, string $meta_key [ , mixed $meta_value = '' ] )
タームのメタ情報を削除する。

register_taxonomy_for_object_type(2014年5月22日 登録)

bool register_taxonomy_for_object_type( string $taxonomy, string $object_type )
投稿タイプにタクソノミーを割り当てる。

the_feed_link(2012年2月7日 登録)

void the_feed_link( string $anchor [ , string $feed = '' ] )
フィードのリンクを表示する。

最終更新日時 : 2011-12-08 13:56