WordPressのパンくずリストのカテゴリーの選び方について

パンくずリストは、現在地までの経路を順番に並べたリンクのことで、Webページの上部などに表示されています。基本のパンくずリストは、ページのリンクを階層順に表示していく形式で、パンくずリストのほとんどがこのタイプです。

WordPressで階層順のパンくずリストを作成する場合、親ページを設定できる固定ページは、その親ページを取得して階層順で表示できます。
しかし、親ページを設定できない投稿記事ページは、親ページを取得して表示できません。(あたりまえです)

投稿記事ページの場合は、カテゴリーを親ページとして表示するやり方が一般的で、パンくずリストの表示機能を持った WordPressテーマも多くがそうしています。

また、カテゴリーは階層構造にできるのでカテゴリーも階層順に表示していくのが一般的です。

例: HOME > 親カテゴリー > 子カテゴリー > 記事タイトル

階層順に表示していくタイプで問題になるのが、カテゴリーが複数設定されている場合に「どれかひとつカテゴリーを選ぶ」必要があるという点です。すべてのカテゴリーの親カテゴリーを表示するパンくずリストは作れません。(作れると思いますが大変なことになります)

実際、パンくずリスト機能のある WordPressテーマは何かしらのひとつを選んで表示しています。
きちんと調べてはいませんが、名前の昇順で最初のカテゴリを選択するパターンが多いように思います。(ID順も多いかも)

前置きが長くなりましたが、今回の記事では WordPressでパンくずリストを自作する際のカテゴリーの選び方について考えてみようと思います。

この記事は、あくまで個人的な見解です。また、まちがっている箇所等あるかもしれません。

目次

どんな選び方があるのか

まず、名前順以外の選び方について考えてみます。

パンくずリストに表示するカテゴリーを取得する場合、一般的に使用されるのが get_the_category() です。

get_the_category() の内部では、 get_the_terms() を使用しています。

get_the_category() の戻り値は、カテゴリーのオブジェクトの配列になっていて、その順序はカテゴリー名の昇順です。

例: オブジェクトの配列

Array
(
    [0] => WP_Term Object
        (
            [term_id] => 35
            [name] => カテゴリー 1
            [slug] => category-1
            [term_group] => 0
            [term_taxonomy_id] => 35
            [taxonomy] => category
            [description] => This is a description for the category-1
            [parent] => 0
            [count] => 3
            [filter] => raw
        )

    [1] => WP_Term Object
        (
            [term_id] => 36
            [name] => カテゴリー 2
            [slug] => category-2
            [term_group] => 0
            [term_taxonomy_id] => 36
            [taxonomy] => category
            [description] => This is a description for the category-2
            [parent] => 35
            [count] => 2
            [filter] => raw
        )

)

例: カテゴリーの取得

$cats = get_the_category();
$cat_name = $cats[0]->name; // カテゴリー 1

このようにして取得すると名前順で選ばれてしまいます。

そこで、カテゴリーのオブジェクトの配列を並び替える (ソートする) ことで選び方を変更できるようにします。

ソートするには、 wp_list_sort() が便利です。第3引数にはソートの昇降順を指定できます。

例: 並べ替えて取得

$cats = get_the_category();
$sort_cats = wp_list_sort( $cats, 'term_id', 'DESC' );
$cat_name = $sort_cats[0]->name; // カテゴリー 2

このように、カテゴリーのオブジェクトのプロパティ別にソートしてから取得すると、例えば、サイトに一番多く設定されているカテゴリーを選んだりできるようになります。

例: 設定数 (count) でソート

$cats = get_the_category();
$sort_cats = wp_list_sort( $cats, 'count', 'DESC' );
$cat_name = $sort_cats[0]->name; // カテゴリー 1

以上のように、「カテゴリーのオブジェクトのプロパティを利用する」とカテゴリーの選び方を色々と変更できると思います。

親子関係はどうなるのか

何かしらのカテゴリーをひとつ選択して表示したら、その親であるカテゴリーも階層順に表示していくことになります。

この時、親子関係のあるカテゴリーがそれぞれ指定してあるページでは、子カテゴリーが表示されない場合が出てきます。(分かりづらいかもしれません)
そうなるのは、ソート結果の順序によっては親の方が選ばれる可能性があるためです。
それで問題は無いと言えば無いのですが、せっかく親子共に設定してあるので、階層順に表示させたい感じもします。

例: HOME > 親カテゴリー > 記事タイトル
子も設定されているのに表示されない場合もある。

例: HOME > 親カテゴリー > 子カテゴリー > 記事タイトル
必ずこのようにしたい。

さらに、子を飛び越して親と孫カテゴリーを設定した場合も、孫カテゴリーが表示されずに親カテゴリーだけが表示される可能性があります。(ややこしくなってきました)

どういう役割があるのか分かりませんが、WordPressのカテゴリーの階層構造は、子を飛び越して孫カテゴリーを設定できます。

: HOME > 親カテゴリー > 子カテゴリー > 孫カテゴリー > 記事タイトル
親と孫だけの場合にもこのようにしたい。

これはどうやって実現すればいいのか考えてみます。

まず、「設定されているカテゴリーの祖先カテゴリーをすべて取得」します。
そして、「設定されているカテゴリーの中から、その祖先カテゴリーを除外」します。
そうすれば、祖先のカテゴリーも設定してあるページで最下層のカテゴリーだけが選ばれるようになります。

祖先のカテゴリーを取得するには、 get_ancestors() を使うと便利です。この関数は、下層から上層の順で祖先のIDを返します。

例: コード

$ancestors_id = array(); // 設定されているカテゴリーのすべての祖先のIDの配列
$children = array(); // すべての祖先を除外した残りのカテゴリーのオブジェクトの配列

// 設定されているカテゴリーの祖先カテゴリーのIDを取得	
foreach ( $cats as $cat ) {
    if ( $cat->parent !== 0 ) {
        $anc_ary = get_ancestors( $cat->term_id, 'category' );
        foreach ( $anc_ary as $value ) {
            $ancestors_id[] = $value;
        }
    }
}

// 設定されているカテゴリーから祖先カテゴリーを除外
foreach ( $cats as $cat ) {
    if ( ! in_array( $cat->term_id, $ancestors_id, true ) ) {
        $children[] = $cat;
    }
}

$cat_name = $children[0]->name; // 最下層のカテゴリーから選択

$cat_ancestors_id = get_ancestors( $children[0]->term_id, 'category' ); // 祖先のID
$cat_ancestors_id = array_reverse( $cat_ancestors_id ); // 反転する

// 祖先カテゴリーを表示
foreach ( $cat_ancestors_id as $anc_id ) {
    echo '<li><a href="' . get_category_link( $anc_id ) . '">'
    . get_cat_name( $anc_id ) . '</a></li>';
}
/* 実際に表示する場合は、適宜エスケープ処理をしてください。*/

設定されてないものを除く

前項では、最下層のカテゴリーをひとつ選択した後、そのカテゴリーの親カテゴリーを階層順にすべて表示します。しかし、設定されてない子カテゴリーは表示しないという考えもあるかもしれません。(もうどうでもいいことです)

例: HOME > 親カテゴリー > 孫カテゴリー > 記事タイトル
子カテゴリーは設定されてないので表示しないようにする。

これはどうやるのか考えてみます。

まず、「選択されたカテゴリーの祖先カテゴリーのIDをすべて取得」します。(前項で取得済み)
そして、「設定されているカテゴリーのIDをすべて取得」します。
最後に、「設定されているカテゴリーのID」と、その「祖先カテゴリーのID」を比較して、それらが一致したものを取得します。
そうすれば、「設定されているカテゴリー」に存在しない「祖先カテゴリー」は除外されます。

例: コード

/* 前項から続き */
$cat_ancestors_id = get_ancestors( $children[0]->term_id, 'category' ); // 祖先のID
$cat_ancestors_id = array_reverse( $cat_ancestors_id ); // 反転する

$current_ancestors = array(); // 設定されている祖先のIDの配列

// 設定されているすべてのカテゴリーのIDを取得
foreach ( $cats as $cat ) {
    $categories_id[] = $cat->term_id;
}

// 祖先IDのうち設定されているカテゴリーのIDと一致するものを取得
foreach ( $cat_ancestors_id as $value ) {
    if ( in_array( $value, $categories_id, true ) ) {
        $current_ancestors[] = $value;
    }
}

// 祖先カテゴリーを表示
foreach ( $current_ancestors as $anc_id ) {
    echo '<li><a href="' . get_category_link( $anc_id ) . '">'
    . get_cat_name( $anc_id ) . '</a></li>';
}
/* 実際に表示する場合は、適宜エスケープ処理をしてください。*/

まとめ

今回は、書いていて自分でも何を言っているのか分からなくなる時もありましたが、パンくずリストのカテゴリーの表示についての考えが整理できたように思います。

パンくずリストを追加できるプラグインには表示をカスタマイズできるものもありますし、カテゴリーをどのように表示するかは、それぞれのサイトに合わせて判断していくことになるのかなと思います。
ちなみに、当ブログのテーマは、設定されたカテゴリーがすべて表示されるようになってます…。

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です。