カスタム投稿タイプで更新した記事も、月別のアーカイブを表示したい時があると思います。
これが簡単なようで意外とハマリました。ちなみに、「『アーカイブページ』内の記事」の表示のことではありません。今回は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」に軍配が上がったのではないでしょうか?
でわ!