カスタム投稿タイプで更新した記事も、月別のアーカイブを表示したい時があると思います。
これが簡単なようで意外とハマリました。ちなみに、「『アーカイブページ』内の記事」の表示のことではありません。今回は2通りの方法をご紹介いたします。
function.phpに追記する方法
だいたいこれにぶち当たると思います。
至極簡単で、functions.phpに以下のコードを追記します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
//投稿タイプ保管用
$my_archives_post_type = ‘post’;
//Where書き換え
add_filter( ‘getarchives_where’, ‘my_getarchives_where’, 10, 2 );
function my_getarchives_where( $where, $r ) {
global $my_archives_post_type;
if ( !array_key_exists( ‘post_type’, $r ) ) {
return $where;
}
$target = $r[‘post_type’];
$new_where = str_replace( “‘post'”, “‘{$target}'”, $where );
$my_archives_post_type = $target;
return $new_where;
}
//出力URL書き換え(末尾にpost_typeくっつけるだけ)
add_filter( ‘get_archives_link’, ‘my_get_archives_link’ );
function my_get_archives_link( $link_html ) {
global $my_archives_post_type;
if ( ” != $my_archives_post_type ) {
$link_html = preg_replace( “/\<a\shref\=\'([^\”]+)\’\>/”, “<a href=’$1&post_type={$my_archives_post_type}’>”, $link_html );
}
return $link_html;
}
|
なにをやっているか?
add_filter(‘getarchives_where’ , ” );
関数リファレンス/add filter – WordPress Codex 日本語版
フィルターは、様々な種類のテキストがデータベースまたはブラウザ画面に送信される前に WordPress が変更を行うフックです。プラグインは、フィルター API を利用して、指定したテキストをその時点で変更する PHP 関数を実行できます。フィルターフックの一覧は プラグイン_API/フィルターフック一覧 を参照してください。
1
|
add_filter( ‘getarchives_where’, ‘my_getarchives_where’, 10, 2 );
|
wp_get_archivesなどでアーカイブを取得するために、内部的に日付の検索を行う(という解釈でいいのか…)のですが、このフィルターを利用することで、アーカイブの取得条件を変更できます。
ここで実行される関数my_getarchives_where()は、「$where」と「$r」を受け取っていますが、これはgetarchives_whereをフックするときに渡される変数で、「$r」には、wp_get_archives()が実行されるときのパラメータが展開されたものが入っています。
キーワード | 省略時の値 | 意味 |
---|---|---|
type | ‘monthly’ | アーカイブ種別を指定(’daily’、’weekly’、’monthly’、’yearly’、’postbypost’、’alpha’など) |
limit | ” | 表示件数(正数) |
format | ‘html’ | 表示形式を指定(’html’、’link’、’option’など) |
before | ” | リンク名の前に連結する文字列 |
after | ” | リンク名の後に連結する文字列 |
show_post_count | false | 投稿件数を表示する場合はtrue、表示しない場合はfalse |
echo | 1 | 表示する場合は1、文字列として取得する場合は0 |
「$where」には、デフォルトで「WHERE post_type = ‘post’ AND post_status = ‘publish’」が格納されています。これはデータベースの抽出条件ですね。
wp_get_archives:WordPress私的マニュアル
!array_key_exists()
1
|
bool array_key_exists ( mixed $key , array $array )
|
$keyが、その後の引数である$arrayに含まれているかどうかを判断しています。
今回の場合はifの中で直前に「!」がついているので、含まれていない場合に{}内の処理をするわけですが、これはつまり、渡ってきた「$r」のパラメータの中に「post_type」が無ければ、 $whereをデフォルトのまま返して終わるということです。
PHP: array_key_exists – Manual
str_replace( “‘post’”, “‘{$target}’”, $where );
その下で、変数「$target」に、そのpost_typeを代入しています。
直後、str_replace()で$whereの中の’post’を「$target」に置換して「$new_where」に保存して、返しています。
1
|
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
|
add_filter(‘get_archives_link’ , ” );
リンクテキストを返す直前にget_archives_linkフィルターが実行される。$link_htmlには、生成されたリンクテキストの内容が格納されている。
リンクを出力するタイミングで、書き換え用の関数「my_get_archives_link()」を実行します。ここで受け取る値は上記のとおり、生成されたリンクテキスト。つまり「アーカイブリンク」です。
外で定義した$my_archives_post_typeをglobal変数として定義します。
それが空でなければif(){~}内の処理を実行します。
preg_replace( “/\/”, ~ );
1
|
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = –1 [, int &$count ]] )
|
$subjectを$replacementで入れ替えるために$patternで検索します。
今回の場合は$link_htmlから、「\」という条件で検索します。
ようするに「」のことなのですが、「[^\”]+」がキモです。これは「『”』以外の文字が1個以上続いている」箇所を表しています。
「[^\”]+」に該当した箇所は「」の中の「$1」に挿入されます。
これで置換完了です。直後、$link_htmlを返します。
「wp_get_archive()」でpost_typeを指定する
本来そのような指定の仕方では何の意味もないのですが、上記のようにコードを書くことで「post_type」が機能します。
1
|
wp_get_archives(‘type=monthly&post_type=カスタム投稿名’);
|
テンプレートタグ/wp get archives – WordPress Codex 日本語版
これで、通常はデフォルトの投稿しか出力しない「wp_get_archive」でカスタム投稿タイプを出力できるようになりました!
月ごとのアーカイブへのURLが以下のように出力されます。
1
2
|
http://ドメイン/?m=201501&post_type=post //(通常)
http://ドメイン/?m=201501&post_type=カスタム投稿タイプ名 //(カスタム投稿)
|
…ですが、注意事項として
- 以降のwp_get_archivesは全て書き換わってしまう
- 「パーマリンク設定」が「デフォルト」以外だと機能しない。
と、すこし不便です…
「Custom Post Type Permalinks」を使う
「Custom Post Type Permalinks」ダウンロード
これをインストールして有効にすることで、上記のように「post_type」の指定が機能します。
こちらを使ったほうが圧倒的に良い印象です。
[設定]>[パーマリンク設定]から、カスタム投稿ごとに細かいパラメータの付き方も指定できるようになります。
パーマリンク設定で「投稿名」を指定している状態です。
今までと同様に記事単体のページのURLですので、「/%postname%/」を消したURLがアーカイブページとなります。
あとは「archive-投稿タイプ名.php」でテンプレートファイルを作って、おなじみの
1
2
3
4
5
6
7
|
if(have_posts()){
while(have_posts()){
the_post();
~~~ループで表示したい項目の処理
}
}
|
で問題ないかと思います。
以上、2通りのやり方をご紹介いたしました。
ここは「Custom Post Type Permalinks」に軍配が上がったのではないでしょうか?
でわ!