相変わらずのフォーラムネタです。同じようなトピックが散見されますので、ここらで決定打を放ちましょう。もう、カテゴリー別×日付別アーカイブ問題で悩まなくて OK! 78364!
幸いなことに、デフォルトパーマリンクを使用して http://example.com/?m=2010&cat=123 のようにカテゴリーと日付を指定さえすれば該当する記事達を取得することはできるので、これを利用することにします。
仕様を決める
- 普通のカテゴリーリンクをクリックする。
- そのカテゴリーのアーカイブが表示される。
当該カテゴリーを含む記事の年/月/日(以下、日付)アーカイブリストを作成します。これはクエリを工夫すれば良さそうです。 - そのアーカイブのパーマリンクは http://example.com/?m=2010&cat=123 の形式になっている。
2.で取得したアーカイブのパーマリンクは ?m=2010 止まりなので、カテゴリの指定を追加します。 - そのリンクをクリックすると、選択したカテゴリーかつ選択した日付の記事一覧を表示する。
これはWordPress の基本機能。
wp_get_archives はフックできるか?
ソースを見ると、アーカイブ取得のクエリに getarchives_where, getarchives_join のフィルタが使われています。なんてラッキー!もうデキたも同然です。これらのフィルタでは、実行しようとしているクエリ(SQL文)に対して独自の WHERE句, JOIN句 を追加することができます。WHERE は条件の指定、JOIN はテーブルの結合。カテゴリーを指定する条件を加えれば OK ですね。
wp-includes/general-template.php 800行目〜
$where = apply_filters('getarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r );
$join = apply_filters('getarchives_join', "", $r);
指定カテゴリーを含む記事の日付別アーカイブを取得する
function my_getarchives_join($join, $r){
global $wpdb;
return
" LEFT JOIN $wpdb->term_relationships as r ON $wpdb->posts.ID = r.object_ID
LEFT JOIN $wpdb->term_taxonomy as t ON r.term_taxonomy_id = t.term_taxonomy_id
LEFT JOIN $wpdb->terms as terms ON t.term_id = terms.term_id";
}
add_filter('getarchives_join', 'my_getarchives_join', 10, 2);
まず、別々になっている投稿のテーブルとカテゴリーのテーブルを結合します。これで投稿を絞るときにカテゴリーを条件として使用できるようになります。
function my_getarchives_where($where, $r){
return $where .
" AND t.taxonomy = 'category' AND terms.term_id = ".get_query_var('cat');
}
add_filter('getarchives_where', 'my_getarchives_where', 10, 2);
カテゴリーID を指定します。
日付別アーカイブのリンクをカテゴリ別×日付別アーカイブのリンクにする
ここでは「年別アーカイブ」について実現することにします。wp_get_archives の内部を見ると get_year_link で年別アーカイブのリンクを取得しています。
wp-includes/general-template.php 841行目
$url = get_year_link($arcresult->year);
get_year_link の内部では、リンク作成後に year_link フィルタを呼んでいます。
wp-includes/linkl-template.php 295行目
return apply_filters('year_link', trailingslashit(get_option('home')) . '?m=' . $year, $year);
おー これは楽チンですね、後ろに &cat=123
などと追加すれば OK です。
function my_year_link($url, $year){
global $wp_rewrite;
$yearlink = $wp_rewrite->get_year_permastruct();
if(empty($yearlink))
return $url . '&cat=' . get_query_var('cat');
return $url;
}
add_filter('year_link', 'my_year_link', 10, 2);
カテゴリページでのみ有効にする
サイドバーでは通常のブログ全体のアーカイブを表示するかもしれませんので、これらの変更は category.php でのみ有効にします。あとは、仕様2.のクリックではアーカイブ表示、仕様4.の時は記事一覧表示の処理を加えます。仕様3.のリンクをクリックすると、カテゴリーが指定されているため category.php が実行されます。なので、これら一連の処理は category.php 内で完結できます。
<?php
function my_year_link($url, $year){
global $wp_rewrite;
$yearlink = $wp_rewrite->get_year_permastruct();
if(empty($yearlink))
return $url . '&cat=' . get_query_var('cat');
return $url;
}
function my_getarchives_where($where, $r){
return $where .
" AND t.taxonomy = 'category' AND terms.term_id = ".get_query_var('cat');
}
function my_getarchives_join($join, $r){
global $wpdb;
return
" LEFT JOIN $wpdb->term_relationships as r ON $wpdb->posts.ID = r.object_ID
LEFT JOIN $wpdb->term_taxonomy as t ON r.term_taxonomy_id = t.term_taxonomy_id
LEFT JOIN $wpdb->terms as terms ON t.term_id = terms.term_id";
}
add_filter('year_link', 'my_year_link', 10, 2);
add_filter('getarchives_where', 'my_getarchives_where', 10, 2);
add_filter('getarchives_join', 'my_getarchives_join', 10, 2);
get_header(); ?>
<body>
<ul>
<?php
if(is_year()) : // 日付があれば、日付×カテゴリなので当該記事一覧を表示する。
while(have_posts()) :
the_post();
?><li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li><?php
endwhile;
else: // 通常のカテゴリリンクの場合は、アーカイブを表示する。
wp_get_archives('type=yearly');
endif;
?>
</ul>
</body>
<?php get_footer();
remove_filter('year_link', 'my_year_link', 10, 2);
remove_filter('getarchives_where', 'my_getarchives_where', 10, 2);
remove_filter('getarchives_join', 'my_getarchives_join', 10, 2);
?>
一部のカテゴリーのみ上記アーカイブ表示をする
例えば、カテゴリーID = 12, 34 のときのみ、このアーカイブ表示をして、他のカテゴリーではまた別の表示にする場合。
- archives-by-category.php(例)を作成して上記コードを記述。
- your-category.php(例)を別途お好みな内容で作成します。
- category.php に以下を記述。
<?php $post = $wp_query->post; if(in_category('12') || in_category('34')){ include(TEMPLATEPATH . '/archives-by-category.php'); }else{ include(TEMPLATEPATH . '/your-category.php'); } ?>
wp_get_archives 実行時に getarchives_where, getarchives_join, year_link フィルタをフックしてカテゴリーを設定すれば、他のシチュエーションでも実現可能です。single.php で表示記事と同じカテゴリの年月アーカイブを表示、とか。チャレンジしてみてくださいー。
参照:フォーラム
2つの特定カテゴリに年別アーカイブを表示させたい動作確認バージョン
- WordPress 2.9.1
指定カテゴリーを含む記事の日付別アーカイブ
カテゴリー毎の日付別アーカイブを表示する | wpxtreme http://t.co/mJqCmth
カテゴリー毎の日付別アーカイブを表示する | wpxtreme http://t.co/eKmNWHDA #wordpress #wp
古い記事だけどこちらも独自でやる方法