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

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

サイト運営

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

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

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

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

通常のアーカイブを年単位に変更する方法

通常のアーカイブは月単位で表示されますが、それを年単位に変更するのは簡単です。

add_filter( 'widget_archives_args','my_archives');
function my_archives( $content ){
	$content['type'] 	= 'yearly';
	$content['after'] 	= '<span class="year-name">年</span>'; //200Xの後に"年"を表示
	$content['limit'] 	= 15; //n年分を表示、この場合5年
	return $content;
}

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

検索して色々見て検討した中で、一番簡単な方法は以下のコードでした。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]&paged=$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;
	
	$cat = get_category( $cat_ID );

	//親カテゴリーの場合は、直下に記事がある場合と子カテゴリまで含む場合をORで結ぶ

	if($cat->parent==0){
		$query="
		SELECT YEAR(post_date) AS post_year,count(*) AS num
		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{
		$query="
			SELECT YEAR(post_date) AS post_year,count(*) AS num
			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
		";
	}
	$results = $wpdb->get_results($wpdb->prepare($query));
	?>
	<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; ?>年<span class="post-count"><?php echo $result->num; ?></span></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(){
	ob_start();
	if(is_category()){
        $cat_id = get_query_var('cat'); 
	}else if(is_single()){
		$cat = get_the_category();

		if(isset($cat[0])){
			$cat = $cat[0];
			$cat_name = $cat->name;
			$cat_id   = $cat->cat_ID;
		}else{
			return;
		}
	}else{
		return ob_get_clean();
	}

	wp_get_category_archive($cat_id);
	return ob_get_clean();
});

使い方

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

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

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

[cat_archive]

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

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

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

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

参考記事

まとめ

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

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

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

この記事を書いた人
ブーン

はるばる日本よりオランダ王国へやってまいりました。
自分の経験が少しでも参考になれば嬉しいです。
お問い合わせは、『こちら』からお願い致します。

\ブーンをフォロー/
スポンサーリンク
サイト運営
\シェアお願いします!/
\ブーンをフォロー/
こんな記事も読まれています

失敗しないレンタルサーバーランキング

mixhost

不正アクセスに強くて使いやすいおススメサーバー
\本サイトで利用中/
メリット①:自動ウィルス駆除対応
メリット②:サイトの表示速度が速い!
メリット③:転送量の上限が多い!
メリット④:自由にプラン変更ができ、アクセス増にも対応できる!
メリット⑤:バックアップデータが無料で復元できる!
メリット⑥:Wordpressが簡単にインストールできる!
メリット⑦:どのプランでも初期費用が無料!
メリット⑧:10日間の無料お試し期間と30日の返金保証!

Conoha Wing

国内Wordpress最速の最強サーバー
メリット①:圧倒的な表示速度
メリット②:レンタルサーバーと独自ドメインがセットでお得◎
メリット③:プラン変更はすべてのプランで自由自在
メリット④:一か月の利用転送量の制限が緩い(9TB~)
メリット⑤:WordPresサイトの移行が簡単

エックスサーバー

国内シェアNo1の安定性と実績が魅力。ALL SSDで死角なしの万能サーバー。
メリット①:サイトの表示速度が安定して速い!
メリット②:アクセス負荷に強くて安定性が高い!
メリット③:24時間365日の充実サポートで安心!電話サポートもあり!
メリット④:転送量が多い!
メリット⑤:自動バックアップ機能付き!
メリット⑥:WordPressが簡単にインストールできる!
メリット⑦:10日の無料お試し期間がある!

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