WordPress にはタグやカテゴリー、月ごとに記事一覧を表示してくれるアーカイブページがある。パーマリンクの設定がデフォルトの場合、タグだと http://{サイトURL}/?tag={タグスラッグ}
、投稿名の場合、 http://{サイトURL}/tag/{タグスラッグ}/
といった感じのURLになる。でタグやカテゴリーは +
オペレーターを使用して複数のワードを指定できる。例えば、wordpress
と gcp
両方のタグを持つ記事を列挙したい場合、http://{サイトURL}/tag/wordpress+gcp
としてやれば良い。しかし、この時に、アーカイブのタイトルが最初のワードのみになってしまうという問題がある。これを解決する方法を見つけたので記しておく。
複数タグを指定してるのにタイトルは単数
実際このサイトのトップメニューは
- WordPress -> 初級
- WordPress -> 中級
- WordPress -> 上級
というサブメニューを作っているが、これも、http://{サイトURL}/tag/wordpress+初級
といった具合にアーカイブページにリンクさせてある。で、その時にページタイトルがいつも “WordPress” だけなので、これを “WordPress + 初級” にしたい。なんとかならないのかなあ、と思い修正方法を調べた。
あいにく、Web 検索では解決方法が見つからず、自分でコードを書くことになった。
get_the_archive_title フィルターフック
このアーカイブページの表示を扱うのは、テンプレートファイルだと archive.php
に該当する。そして、the_archive_title() が使用されている。この関数を調べると、get_the_archive_title
というフィルターフックがあるのが分かる。これを使って出力結果を変更してやれば良い。
1 2 3 4 5 6 7 8 |
/** * Filters the archive title. * * @since 4.1.0 * * @param string $title Archive title to be displayed. */ return apply_filters( 'get_the_archive_title', $title ); |
コード
以下のコードをテーマの funcitons.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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
/** * Modifies the archive title for multiple terms queries. */ class ArchiveTitleMultipleTerms { public function __construct() { add_filter( 'get_the_archive_title', array( $this, 'replyToModifyArchiveTitle' ) ); } public function replyToModifyArchiveTitle( $sArchiveTitle ) { if ( ! is_archive() ) { return $sArchiveTitle; } /** * @var WP_Term */ $_oWPTerm = get_queried_object(); if ( ! ( $_oWPTerm instanceof WP_Term ) ) { return $sArchiveTitle; } $_sQueriedTaxonomySlug = $_oWPTerm->taxonomy; $_aQueriedTerms = ( array ) $GLOBALS[ 'wp_query' ]->tax_query->queried_terms; if ( ! isset( $_aQueriedTerms[ $_sQueriedTaxonomySlug ] ) ) { return $sArchiveTitle; } $_aQueriedTermsDigged = $_aQueriedTerms[ $_sQueriedTaxonomySlug ]; $_aQueriedTermSlugs = isset( $_aQueriedTermsDigged[ 'terms' ] ) ? ( array ) $_aQueriedTermsDigged[ 'terms' ] : array(); if ( count( $_aQueriedTermSlugs ) < 2 ) { return $sArchiveTitle; } // At this point, multiple terms are queried. $_oWPTaxonomy = get_taxonomy( $_sQueriedTaxonomySlug ); if ( empty( $_oWPTaxonomy ) ) { return $sArchiveTitle; } $_sArchiveTitle = sprintf( __( '%1$s: %2$s' ), $_oWPTaxonomy->labels->singular_name, implode( ' + ', $this->___getTermsLabels( $_aQueriedTermSlugs, $_sQueriedTaxonomySlug ) ) ); return $_sArchiveTitle; } private function ___getTermsLabels( array $aTermSlugs, $sTaxonomySlug ) { $_aTermLabels = array(); foreach( $aTermSlugs as $_sTermSlug ) { $_oTerm = get_term_by( 'slug', $_sTermSlug, $sTaxonomySlug ); $_aTermLabels[] = $_oTerm->name; } return $_aTermLabels; } } new ArchiveTitleMultipleTerms; |
ざっくり何をしてるのかというと、$GLOBALS[ 'wp_query' ]->tax_query->queried_terms
の中にDBクエリに使われたタクソノミーのターム(キーワード)が入っているので、それが複数の場合、それらからタームの名称を抜き出して、「分類名: ターム」 から 「分類名:ターム1 + ターム2」という表記に置換するというもの。
結果
これで、複数のタグを指定した時にきちんとその複数のタグが表示される。
理論上、タグ (post_tag
) 以外のカスタムタクソノミーにも対応してるはずだけど、きちんと検証はしてない。ちなみに、ビルトインのカテゴリー category
タクソノミーは、複数のタームでクエリがかけられていても前述の $GLOBALS[ 'wp_query' ]->tax_query->queried_terms
には最初のターム以外は切り捨てて一つだけしか格納してくれないみたい。これはバグっぽいけど意図されてるかもしれないし深くは掘って見てない。