コーポレートサイトでは、記事のカテゴリ単位でアーカイブを表示しなければならない場面が、そこそこあります。
しかし、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');
}
参考記事
まとめ
カテゴリー単位のアーカイブというのは、簡単にできるようで結構難しいです。
調べるといろいろ出てきますが、情報が古く本当に動くのか確認するのが大変です。
今回ご紹介した内容は、今でも使えるのでカスタマイズすれば使える場面は多いと思います。