お問い合わせはコチラから

WordPressでカテゴリの年ごとのアーカイブを出力する

サイト運営

コーポレートサイトでは、記事のカテゴリ単位でアーカイブを表示しなければならない場面が、そこそこあります。

しかし、Wordpressのアーカイブページは、カテゴリの概念がありません。アーカイブウィジェットだけでなく、Wordpressの関数を使っても簡単にはできません。

色々調べても、記事の内容が古かったり、分かりにくい内容が多かったのですが、最終的に実現方法にたどり着きました。

この記事では、カテゴリごとに年単位のアーカイブを出力する方法をまとめておきます。

カテゴリの年ごとのアーカイブを表示するコード

検索して色々見て検討した中で、一番簡単な方法は以下のコードでした。functions.phpに貼り付けることで、wp_get_category_archive関数が使えるようになります。

WordPressで指定したカテゴリーの年別アーカイブを作成する | webOpixel http://www.webopixel.net/wordpress/236.html の改造版。プラグイン有効時にflush_rules()か、パーマリンク設定の更新が必要。

<?php

function extend_date_archives_add_rewrite_rules() {
  add_rewrite_rule( 'category/([^/]+)/date/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?category_name=$matches[1]&year=$matches[2]&monthnum=$matches[3]&day=$matches[4]&feed=$matches[4]', 'top' );
	add_rewrite_rule( 'category/([^/]+)/date/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/?$', 'index.php?category_name=$matches[1]&year=$matches[2]&monthnum=$matches[3]&day=$matches[4]', 'top' );
	add_rewrite_rule( 'category/([^/]+)/date/([0-9]{4})/([0-9]{1,2})/?$', 'index.php?category_name=$matches[1]&year=$matches[2]&monthnum=$matches[3]', 'top' );
	add_rewrite_rule( 'category/([^/]+)/date/([0-9]{4})/?$', 'index.php?category_name=$matches[1]&year=$matches[2]', 'top' );
	add_rewrite_rule( 'category/([^/]+)/date/([0-9]{4})/page/([0-9]+)/?$', 'index.php?category_name=$matches[1]&year=$matches[2]&page=$matches[3]', 'top' );//ページネーション対応
}
add_action('wp_loaded', 'extend_date_archives_add_rewrite_rules');


function extend_date_wp_title ($title , $sep, $seplocation) {
	if(is_date()){
		global $wp_query;
		$cat = get_category( $wp_query->query_vars["cat"]);
		if( $seplocation == "right" ){
			$title = $title." ".$cat->name." ".$sep." ";
		}else {
			$title = " ".$sep." ".$cat->name." ".$title;
		}
	}
	return $title;
}
add_filter('wp_title','extend_date_wp_title', 100 ,3 );

function wp_get_category_archive($cat_ID) {
	global $wpdb;
	

//echo '<pre>';
//echo var_dump($results);
//echo '</pre>';
	$cat = get_category( $cat_ID );
	

	//親カテゴリーの場合は、直下に記事がある場合と子カテゴリまで含む場合をORで結ぶ
	if($cat->parent==0){
		$results = $wpdb->get_results($wpdb->prepare("
			SELECT YEAR(post_date) AS post_year
			FROM $wpdb->posts p, $wpdb->term_relationships tr, $wpdb->term_taxonomy tt, $wpdb->terms t
			WHERE p.ID = tr.object_id
			AND (( tt.parent = $cat_ID ) OR (tt.term_id = $cat_ID ))
			AND t.term_id = $cat_ID
			AND tr.term_taxonomy_id = tt.term_taxonomy_id
			AND p.post_status = 'publish'
			AND p.post_type = 'post'
			GROUP BY post_year
			ORDER BY post_year DESC
		"));
	}else{
		$results = $wpdb->get_results($wpdb->prepare("
			SELECT YEAR(post_date) AS post_year
			FROM $wpdb->posts p, $wpdb->term_relationships tr, $wpdb->term_taxonomy tt, $wpdb->terms t
			WHERE p.ID = tr.object_id
			AND tt.term_id = $cat_ID
			AND t.term_id = $cat_ID
			AND tr.term_taxonomy_id = tt.term_taxonomy_id
			AND p.post_status = 'publish'
			AND p.post_type = 'post'
			GROUP BY post_year
			ORDER BY post_year DESC
		"));
	}

	?>
	<ul class="cat-archive">
	<?php 
	foreach ($results as $result) :?>
	<li><a href="<?php bloginfo('url'); ?>/category/<?php echo $cat->slug;?>/date/<?php echo $result->post_year; ?>"><?php echo $result->post_year; ?>年</a></li>
	<?php endforeach; ?>
	</ul>
<?php
}

オリジナルは、AND tt.term_id = t.term_id = $cat_IDとなっていましたが、ID=1の時しか動かなかったので、分割してあります。

やっている内容は、

  • 前半はURLのリライトルールを定義。
  • 中段でwpdb経由でカテゴリ内の各年の記事数の有無を取得。
  • 最後に記事がある年だけリスト形式で出力

するという流れです。

この方法は、各年に含まれる記事のリンクまでは取得していないのがミソです。あくまでも各年にカテゴリーの記事の存在有無だけしか判定していません。

もともとWordpressには、URLクエリを指定することでカテゴリ毎に年アーカイブを出す機能があるので、その機能を使っています。子のカスタマイズは、そのリンクを用意するだけです。

更に、クエリパラメータを含むURLをリライトルールで見た目を整えることで、あたかも、新たにカテゴリ毎の年アーカイブの機能を実現しているように見せています。

オリジナルからの変更点

元記事は、階層カテゴリの時に、親カテゴリの直下に記事が無い場合、親カテゴリの記事数が0になってしまうので、SQLで結果が得られませんでした。親カテゴリの場合は親カテゴリ直下の記事と子カテゴリの記事で、親カテゴリに属する記事も対象にするように変更しました。

また、リライトルールがページネーションに対応していなかったので、そこも修正しました。

参考https://gist.github.com/torounit/5106240

ショートコード化

そのままだとサイドバーに設置できないので、ショートコード化します。

カテゴリページと投稿記事で、カテゴリーIDを取得する方法が違うので条件分けします。

add_shortcode('cat_archive',function(){
	if(is_category()){
        $cat_id = get_query_var('cat'); 
	}else{
		$cat = get_the_category();
		$cat = $cat[0];
		$cat_name = $cat->name;
		$cat_id   = $cat->cat_ID;		
	}
	wp_get_category_archive($cat_id);
});

使い方

サイドバーなどのテキストウィジェットに以下のようにショートコードを書くことで、『カテゴリページ』と『記事』でカテゴリの年アーカイブのリストが出力されるようになります。

カテゴリの概念が無いページでは、リストは表示されません。

また、Blogのアーカイブページでも表示されません。blogのアーカイブページで年単位でアーカイブを表示したい場合は、単純に従来のアーカイブで年単位で表示するようにしましょう。

[cat_archive]

アーカイブページで年を取得する

カテゴリごとのアーカイブページで、タイトルに年を表示した方が便利です。

その時はURLのクエリにyearがあるのでそれを取得することで表示できます。

if ( get_query_var('year') ) {
    echo get_query_var('year');
}

参考記事

まとめ

カテゴリー単位のアーカイブというのは、簡単にできるようで結構難しいです。

調べるといろいろ出てきますが、情報が古く本当に動くのか確認するのが大変です。

今回ご紹介した内容は、今でも使えるのでカスタマイズすれば使える場面は多いと思います。

タイトルとURLをコピーしました