この記事は最後に更新してから1年以上経過しています。

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

説明

少し前に投稿した「適切なテンプレートファイルを用意してテンプレート内の振り分け処理を無くす」で説明した通り、特定のカテゴリ専用のテンプレートとして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で提供されたもの。ここではリクエストされたカテゴリ情報を取得しているが、アーカイブページのデータ取得する場合など幅広く使えそうだ。


最終更新 : 2011年12月08日 13:56


お勧め

is_embed(2015年12月23日 更新)

bool is_embed( )
要求されているページが埋め込み投稿ページか調べる。

get_custom_header_markup(2017年4月7日 更新)

string get_custom_header_markup()
カスタムヘッダーのHTMLパーツを取得する。

wp_set_password(2013年5月5日 更新)

void wp_set_password( string $password, int $user_id )
ログインパスワードを設定する。

get_category(2011年5月25日 更新)

mixed get_category( mixed $category [ , string $output = OBJECT [ , string $filter = 'raw' ] ] )
IDを指定してカテゴリー情報を取得する。

get_body_class(2012年6月23日 更新)

array get_body_class( [ string $class = '' ] )
bodyタグのclass属性値を取得する。