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

子カテゴリのアーカイブページを親カテゴリ用のテンプレートファイルで表示しよう - 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で提供されたもの。ここではリクエストされたカテゴリ情報を取得しているが、アーカイブページのデータ取得する場合など幅広く使えそうだ。

関連

お勧めコンテンツ

wp_extract_urls(2013年10月28日 登録)

array wp_extract_urls( string $content )
テキスト内のURLを抽出する。

esc_url_raw(2011年4月7日 登録)

string esc_url_raw( string $url [ , array $protocols = null ] )
URL文字列を調べ、データベース向けに余分な文字を取り除いたり、変換したりする。

nocache_headers(2010年5月13日 登録)

void nocache_headers( )
ブラウザのキャッシュを無効にするHTTPヘッダーを出力する。

is_allowed_http_origin(2014年10月29日 登録)

bool is_allowed_http_origin( [ string $origin = null ] )
リクエスト元のオリジンが有効か調べる。

edit_term_link(2015年6月24日 登録)

string edit_term_link( [ string $link = '' [ , string $before = '' [ , string $after = '' [ , object $term = null [ , bool $echo = true ] ] ] ] ] )
タームの編集リンクを表示または取得する。

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