WordPress:階層化パンくずリスト(プラグインなし)とページネーション、ページャー

WordPress:階層化パンくずリスト(プラグインなし)とページネーション、ページャー

テーマをゼロから作ってみる(5)です。

今回は階層化パンくずリストをプラグインを使わずに作ってみます。ページネーションやページャーは WordPress の関数を使えば簡単に実現できます。パンくずリストの方はプラグインを使うか自作するしかないようです。

01ページネーション、ページャー

ページネーションとかページャーとか適当に言葉を使っていますが、要は次の記事や次のページ、または前の記事や前のページへのリンクということでいいと思います。ページが分割されている場合のリンクも同じように呼ぶようです。

これに関係する関数はたくさんあります。

個別投稿ページで前後の投稿へのナビゲーションを表示する関数の

そして、インデックスやカテゴリーページなどで前後のページへのナビゲーションを表示する関数の

があります。

いろいろ試した結果、まずは、

<?php if (is_single()): ?>
<?php the_post_navigation(); ?>
<?php else: ?>
<?php the_posts_pagination(array('mid_size' => 2)); ?>
<?php endif; ?>

でやってみて、カスタマイズの必要が出てくれば、next_post_link, previous_post_link や get_the_posts_pagination を使えばいいでしょう。このコードですと次のように表示されます。

個別記事
インデックス(現在トップページ)

後は CSS で見た目を整えればいけそうです。個別ページの画像のナビゲーションは左右に振ってあります。また、スクリーンリーダーテキストの「投稿ナビゲーション」は CSS で視覚的に消せばいいと思います。その CSS のコードは、Make WordPress Accessible にあります。

02階層化パンくずリスト

下記記事に決定版があります。

パンくずリストに関しては用意された関数はありませんので自作することになります。

まず、現時点では、パンくずリストは記事ページに表示することを前提にし、記事が属するカテゴリーを階層的に示すものとして始めます。記事は複数のカテゴリーを持てますし、階層化されている場合はかなり面倒になります。固定ページやカテゴリーページの場合はさほど難しくないと思われますので後回しです。

自作の階層化パンくずリスト

WordPress が提供しているカテゴリー関連の関数をいろいろながめて構想した結果、流れは次のようになりました。

  • get_the_category で記事が属するカテゴリーを取得する
  • category_parent が 0 のカテゴリーを探し、その cat_ID を取得する
  • category_parent がその cat_ID のカテゴリーを探し、その cat_ID を取得する
  • 3 を繰り返し、記事のカテゴリーヒエラルキー [ 親, 子, 孫, … ] の cat_ID を取得する
  • 各カテゴリーに対し、get_category, get_category_link を使い、階層化カテゴリーツリーを作成する

コードは次のようになります。

function get_imz_breadcrumbs( $post_id ) {

    $categories = get_the_category($post_id);
    $array = array();
    $get_child_category = function($parent) use (&$get_child_category, $categories, &$array){
        foreach($categories as $category){
            if($parent == $category->category_parent){
                $array[] = $category->cat_ID;
                $get_child_category($category->cat_ID);
            }
        }
        return $array;
    };

    if($categories){
        $category_tree = $get_child_category(0);
        $separator = '<li class="separator">/</li>';
        $breadcrumbs = '<ol><li class="breadcrumb-item"><a class="breadcrumb-link" href="'.get_bloginfo('url').'" >HOME</a></li>' . $separator;
        foreach($category_tree as $id){
            $category = get_category($id);
            $category_url = get_category_link( $id );
            $breadcrumbs .= '<li class="breadcrumb-item"><a class="breadcrumb-link" href="' . $category_url . '">' . $category->name . '</a></li>' . $separator;
        }
        echo $breadcrumbs . '<li class="breadcrumb-item">' . get_the_title($post_id) . '</li></ol>';
    }
}

使い方

記事ページであれば、ループ外であっても、

<nav class="breadcrumb"><?php get_imz_breadcrumbs(get_the_ID()); ?></nav>

とすれば、

のように表示されます。とりあえずは CSS で各リストに display: inline を指定して横並びにしています。なお、サンプルでは「トップ」というカテゴリーが表示されていますが、これは get_the_category の返す順序を試すもので説明は次のとおりです。

03get_the_category の戻り値

この関数は現在の投稿が属するカテゴリーを配列で返します。ソースを確認していませんが、その戻り値はカテゴリーID(term_id)の昇順で返ってきます。登録順ということです。

ですので、たとえば親カテゴリーとなる「トップ」を最後に登録した場合は、親カテゴリーは配列の最後になります。具体的には次のとおりです。

array(3) {
  [0]=>
  object(WP_Term)#5030 (16) {
    ["term_id"]=> int(29)
    ["name"]=> string(6) "た行"
    ["slug"]=> string(9) "ta-column"
    ["term_group"]=> int(0)
    ["term_taxonomy_id"]=> int(29)
    ["taxonomy"]=> string(8) "category"
    ["description"]=> string(0) ""
    ["parent"]=> int(53)
    ["count"]=> int(5)
    ["filter"]=> string(3) "raw"
    ["cat_ID"]=> int(29)
    ["category_count"]=> int(5)
    ["category_description"]=> string(0) ""
    ["cat_name"]=> string(6) "た行"
    ["category_nicename"]=> string(9) "ta-column"
    ["category_parent"]=> int(53)
  }
  [1]=>
  object(WP_Term)#5027 (16) {
    ["term_id"]=> int(41)
    ["name"]=> string(3) "と"
    ["slug"]=> string(2) "to"
    ["term_group"]=> int(0)
    ["term_taxonomy_id"]=> int(41)
    ["taxonomy"]=> string(8) "category"
    ["description"]=> string(0) ""
    ["parent"]=> int(29)
    ["count"]=> int(2)
    ["filter"]=> string(3) "raw"
    ["cat_ID"]=> int(41)
    ["category_count"]=> int(2)
    ["category_description"]=> string(0) ""
    ["cat_name"]=> string(3) "と"
    ["category_nicename"]=> string(2) "to"
    ["category_parent"]=> int(29)
  }
  [2]=>
  object(WP_Term)#5028 (16) {
    ["term_id"]=> int(53)
    ["name"]=> string(9) "トップ"
    ["slug"]=> string(3) "top"
    ["term_group"]=> int(0)
    ["term_taxonomy_id"]=> int(53)
    ["taxonomy"]=> string(8) "category"
    ["description"]=> string(0) ""
    ["parent"]=> int(0)
    ["count"]=> int(1)
    ["filter"]=> string(3) "raw"
    ["cat_ID"]=> int(53)
    ["category_count"]=> int(1)
    ["category_description"]=> string(0) ""
    ["cat_name"]=> string(9) "トップ"
    ["category_nicename"]=> string(3) "top"
    ["category_parent"]=> int(0)
  }
}

五十音順でカテゴリーを組んでいるケースですので、「た行」「た」がカテゴリーになっています。そこに最後にカテゴリー「トップ」を登録し、該当記事の get_the_category を取得したケースです。

要は、最上位の親カテゴリーが何番目にあるかはわからないということになります。ですので、上のコードでは、まず category_parent が 0 のカテゴリーを探し出し、その cat_ID を category_parent に持つカテゴリーを探し出すという方法を繰り返しています。

ただし、これでもまだ完全ではありません。複数の親を持つ記事、またはカテゴリーも存在し得ますのでその場合どうするかが問題になります。

その宿題は後々として、とりあえずは階層化パンくずリストが出来上がりました。