WEB制作者向け無料テーマ「Arkhe」をリリースしました

【JSON-LD対応】WordPressでプラグインを使わずにパンくずリストを自動で生成するコードを自作してみた

WordPressでプラグインを使わずにパンくずリストを自動生成する関数を自作してみたので、メモしておこうと思います。

カスタム投稿タイプに紐づいたタクソノミーなどもしっかり表示するように設計しており、(おそらく)全ページ種別に対応できていると思います。

もちろん、パンくずリストはプラグインを使ってもお手軽に実装できます。

ただ、カスタム投稿などを使用したりすると結局コードをいじることになりますよね。
だったら、自分で作ったり理解しているコードを使う方がより柔軟な対応も可能だし、なにかと便利かなと...。

たかがパンくずリストごときにプラグイン入れたくないですしね。笑

【2018 / 12 / 28 更新】
コードの内容を大幅に改良いたしました。

今回は、通常ののパンくずリストの他、スキーマ(schema.org)に対応させたタイプのパンくずリストのコードも紹介しておきます。

※ 改良されたコードのschema.org 対応版はありません(今では JSON-LD対応の方が推奨されているようですので、追加する予定もないです)

目次

パンくずリストを自動生成する関数を定義する

では、パンくずリストを自動生成していくコードを作成していきましょう。

functions.phpに以下のコードをコピペしてください。

以下では旧版と改良版の両方を紹介していますが、改良版をご利用ください。(どのように改良したのかを比較できるように、一応旧版のコードは残しています)

【旧版!】パンくずリスト生成関数

function breadcrumb(){
  global $post;
  $str = '';
  $pNum = 2;
  $str.= '<div id="breadcrumb">';
  $str.= '<ul>';
  $str.= '<li ><a href="'.home_url('/').'" class="home"><span>HOME</span></a></li>';

  /* 通常の投稿ページ  */
  if(is_singular('post')){
    $categories = get_the_category($post->ID);
    $cat = $categories[0];

    if($cat->parent != 0){
      $ancestors = array_reverse(get_ancestors($cat->cat_ID, 'category'));
      foreach($ancestors as $ancestor){
        $str.= '<li><a href="'. get_category_link($ancestor).'"><span>'.get_cat_name($ancestor).'</span></a></li>';
      }
    }
    $str.= '<li><a href="'. get_category_link($cat-> term_id). '"><span>'.$cat->cat_name.'</span></a></li>';
    $str.= '<li><span>'.$post->post_title.'</span></li>';
  }

  /* カスタムポスト */
  elseif(is_single() && !is_singular('post')){
    $cp_name = get_post_type_object(get_post_type())->label;
    $cp_url = home_url('/').get_post_type_object(get_post_type())->name;
  
    $str.= '<li><a href="'.$cp_url.'"><span>'.$cp_name.'</span></a></li>';
    $str.= '<li><span>'.$post->post_title.'</span></li>';
  }

  /* 固定ページ */
  elseif(is_page()){
    $pNum = 2;
    if($post->post_parent != 0 ){
      $ancestors = array_reverse(get_post_ancestors($post->ID));
      foreach($ancestors as $ancestor){
        $str.= '<li><a href="'. get_permalink($ancestor).'"><span>'.get_the_title($ancestor).'</span></a></li>';
      }
    }
    $str.= '<li><span>'. $post->post_title.'</span></li>';
  }

  /* カテゴリページ */
  elseif(is_category()) {
    $cat = get_queried_object();
    $pNum = 2;
    if($cat->parent != 0){
      $ancestors = array_reverse(get_ancestors($cat->cat_ID, 'category'));
      foreach($ancestors as $ancestor){
        $str.= '<li><a href="'. get_category_link($ancestor) .'"><span>'.get_cat_name($ancestor).'</span></a></li>';
      }
    }
    $str.= '<li><span>'.$cat->name.'</span></li>';
  }

  /* タグページ */
  elseif(is_tag()){
    $str.= '<li><span>'. single_tag_title('', false). '</span></li>';
  }

  /* 時系列アーカイブページ */
  elseif(is_date()){
    if(get_query_var('day') != 0){
      $str.= '<li><a href="'. get_year_link(get_query_var('year')).'"><span>'.get_query_var('year').'年</span></a></li>';
      $str.= '<li><a  href="'.get_month_link(get_query_var('year'), get_query_var('monthnum')).'"><span>'.get_query_var('monthnum').'月</span></a></li>';
      $str.= '<li><span>'.get_query_var('day'). '</span>日</li>';
    } elseif(get_query_var('monthnum') != 0){
      $str.= '<li><a href="'. get_year_link(get_query_var('year')).'"><span>'.get_query_var('year').'年</span></a></li>';
      $str.= '<li><span>'.get_query_var('monthnum'). '</span>月</li>';
    } else {
      $str.= '<li><span>'.get_query_var('year').'年</span></li>';
    }
  }

  /* 投稿者ページ */
  elseif(is_author()){
    $str.= '<li><span>投稿者 : '.get_the_author_meta('display_name', get_query_var('author')).'</span></li>';
  }

  /* 添付ファイルページ */
  elseif(is_attachment()){
    $pNum = 2;
    if($post -> post_parent != 0 ){
      $str.= '<li><a href="'.get_permalink($post-> post_parent).'"><span>'.get_the_title($post->post_parent).'</span></a></li>';
    }
    $str.= '<li><span>'.$post->post_title.'</span></li>';
  }

  /* 検索結果ページ */
  elseif(is_search()){
    $str.= '<li><span>「'.get_search_query().'」で検索した結果</span></li>';
  }

  /* 404 Not Found ページ */
  elseif(is_404()){
    $str.= '<li><span>お探しの記事は見つかりませんでした。</span></li>';
  }

  /* その他のページ */
  else{
    $str.= '<li><span>'.wp_title('', false).'</span></li>';
  }
  $str.= '</ul>';
  $str.= '</div>';

  echo $str;
}

※上記コードは古いバージョンです。

【改良版】パンくずリスト生成関数

if ( ! function_exists( 'custom_breadcrumb' ) ) {
  function custom_breadcrumb() {

    // トップページでは何も出力しないように
    if ( is_front_page() ) return false;

    //そのページのWPオブジェクトを取得
    $wp_obj = get_queried_object();

    echo '<div id="breadcrumb">'.  //id名などは任意で
      '<ul>'.
        '<li>'.
          '<a href="'. esc_url( home_url() ) .'"><span>ホーム</span></a>'.
        '</li>';

    if ( is_attachment() ) {

      /**
       * 添付ファイルページ ( $wp_obj : WP_Post )
       * ※ 添付ファイルページでは is_single() も true になるので先に分岐
       */
      $post_title = apply_filters( 'the_title', $wp_obj->post_title );
      echo '<li><span>'. esc_html( $post_title ) .'</span></li>';

    } elseif ( is_single() ) {

      /**
       * 投稿ページ ( $wp_obj : WP_Post )
       */
      $post_id    = $wp_obj->ID;
      $post_type  = $wp_obj->post_type;
      $post_title = apply_filters( 'the_title', $wp_obj->post_title );

      // カスタム投稿タイプかどうか
      if ( $post_type !== 'post' ) {

        $the_tax = "";  //そのサイトに合わせて投稿タイプごとに分岐させて明示的に指定してもよい

        // 投稿タイプに紐づいたタクソノミーを取得 (投稿フォーマットは除く)
        $tax_array = get_object_taxonomies( $post_type, 'names');
        foreach ($tax_array as $tax_name) {
            if ( $tax_name !== 'post_format' ) {
                $the_tax = $tax_name;
                break;
            }
        }

        $post_type_link = esc_url( get_post_type_archive_link( $post_type ) );
        $post_type_label = esc_html( get_post_type_object( $post_type )->label );

        //カスタム投稿タイプ名の表示
        echo '<li>'.
              '<a href="'. $post_type_link .'">'.
                '<span>'. $post_type_label .'</span>'.
              '</a>'.
            '</li>';

        } else {

          $the_tax = 'category';  //通常の投稿の場合、カテゴリーを表示

        }

        // 投稿に紐づくタームを全て取得
        $terms = get_the_terms( $post_id, $the_tax );

        // タクソノミーが紐づいていれば表示
        if ( $terms !== false ) {

          $child_terms  = array();  // 子を持たないタームだけを集める配列
          $parents_list = array();  // 子を持つタームだけを集める配列

          //全タームの親IDを取得
          foreach ( $terms as $term ) {
            if ( $term->parent !== 0 ) {
              $parents_list[] = $term->parent;
            }
          }

          //親リストに含まれないタームのみ取得
          foreach ( $terms as $term ) {
            if ( ! in_array( $term->term_id, $parents_list ) ) {
              $child_terms[] = $term;
            }
          }

          // 最下層のターム配列から一つだけ取得
          $term = $child_terms[0];

          if ( $term->parent !== 0 ) {

            // 親タームのIDリストを取得
            $parent_array = array_reverse( get_ancestors( $term->term_id, $the_tax ) );

            foreach ( $parent_array as $parent_id ) {
              $parent_term = get_term( $parent_id, $the_tax );
              $parent_link = esc_url( get_term_link( $parent_id, $the_tax ) );
              $parent_name = esc_html( $parent_term->name );
              echo '<li>'.
                    '<a href="'. $parent_link .'">'.
                      '<span>'. $parent_name .'</span>'.
                    '</a>'.
                  '</li>';
            }
          }

          $term_link = esc_url( get_term_link( $term->term_id, $the_tax ) );
          $term_name = esc_html( $term->name );
          // 最下層のタームを表示
          echo '<li>'.
                '<a href="'. $term_link .'">'.
                  '<span>'. $term_name .'</span>'.
                '</a>'.
              '</li>';
        }

        // 投稿自身の表示
        echo '<li><span>'. esc_html( strip_tags( $post_title ) ) .'</span></li>';

    } elseif ( is_page() || is_home() ) {

      /**
       * 固定ページ ( $wp_obj : WP_Post )
       */
      $page_id    = $wp_obj->ID;
      $page_title = apply_filters( 'the_title', $wp_obj->post_title );

      // 親ページがあれば順番に表示
      if ( $wp_obj->post_parent !== 0 ) {
        $parent_array = array_reverse( get_post_ancestors( $page_id ) );
        foreach( $parent_array as $parent_id ) {
          $parent_link = esc_url( get_permalink( $parent_id ) );
          $parent_name = esc_html( get_the_title( $parent_id ) );
          echo '<li>'.
                '<a href="'. $parent_link .'">'.
                  '<span>'. $parent_name .'</span>'.
                '</a>'.
              '</li>';
        }
      }
      // 投稿自身の表示
      echo '<li><span>'. esc_html( strip_tags( $page_title ) ) .'</span></li>';

    } elseif ( is_post_type_archive() ) {

      /**
       * 投稿タイプアーカイブページ ( $wp_obj : WP_Post_Type )
       */
      echo '<li><span>'. esc_html( $wp_obj->label ) .'</span></li>';

    } elseif ( is_date() ) {

      /**
       * 日付アーカイブ ( $wp_obj : null )
       */
      $year  = get_query_var('year');
      $month = get_query_var('monthnum');
      $day   = get_query_var('day');

      if ( $day !== 0 ) {
        //日別アーカイブ
        echo '<li>'.
              '<a href="'. esc_url( get_year_link( $year ) ) .'"><span>'. esc_html( $year ) .'年</span></a>'.
            '</li>'.
            '<li>'.
              '<a href="'. esc_url( get_month_link( $year, $month ) ) . '"><span>'. esc_html( $month ) .'月</span></a>'.
            '</li>'.
            '<li>'.
              '<span>'. esc_html( $day ) .'日</span>'.
            '</li>';

      } elseif ( $month !== 0 ) {
        //月別アーカイブ
        echo '<li>'.
              '<a href="'. esc_url( get_year_link( $year ) ) .'"><span>'. esc_html( $year ) .'年</span></a>'.
            '</li>'.
            '<li>'.
              '<span>'. esc_html( $month ) .'月</span>'.
            '</li>';

      } else {
        //年別アーカイブ
        echo '<li><span>'. esc_html( $year ) .'年</span></li>';

      }

    } elseif ( is_author() ) {

      /**
       * 投稿者アーカイブ ( $wp_obj : WP_User )
       */
      echo '<li><span>'. esc_html( $wp_obj->display_name ) .' の執筆記事</span></li>';

    } elseif ( is_archive() ) {

      /**
       * タームアーカイブ ( $wp_obj : WP_Term )
       */
      $term_id   = $wp_obj->term_id;
      $term_name = $wp_obj->name;
      $tax_name  = $wp_obj->taxonomy;

      /* ここでタクソノミーに紐づくカスタム投稿タイプを出力しても良いでしょう。 */

      // 親ページがあれば順番に表示
      if ( $wp_obj->parent !== 0 ) {

        $parent_array = array_reverse( get_ancestors( $term_id, $tax_name ) );
        foreach( $parent_array as $parent_id ) {
          $parent_term = get_term( $parent_id, $tax_name );
          $parent_link = esc_url( get_term_link( $parent_id, $tax_name ) );
          $parent_name = esc_html( $parent_term->name );
          echo '<li>'.
                '<a href="'. $parent_link .'">'.
                  '<span>'. $parent_name .'</span>'.
                '</a>'.
              '</li>';
        }
      }

      // ターム自身の表示
      echo '<li>'.
            '<span>'. esc_html( $term_name ) .'</span>'.
          '</li>';


    } elseif ( is_search() ) {

      /**
       * 検索結果ページ
       */
      echo '<li><span>「'. esc_html( get_search_query() ) .'」で検索した結果</span></li>';

    
    } elseif ( is_404() ) {

      /**
       * 404ページ
       */
      echo '<li><span>お探しの記事は見つかりませんでした。</span></li>';

    } else {

      /**
       * その他のページ(無いと思うけど一応)
       */
      echo '<li><span>'. esc_html( get_the_title() ) .'</span></li>';

    }

    echo '</ul></div>';  // 冒頭に合わせた閉じタグ

  }
}

2019/8/31:【改良版】にて、カスタムタクソノミー周りのコードを少し改善しました。

全ページ種別に対応させているため かなり長いコードですが、その分、様々な知識が詰まったコードになっています。(コメントもブログ用に細かく記述しています。)

WordPress初心者の方は、ひとつひとつ中身を見ていただければ色々な発見もあるかと思いますので ぜひ参考にしていただければと思います。

また、サイトによってはパンくずリストを設置しないページもあると思いますが、サイトによって不要な部分は削除するなりしてスッキリさせてください。

旧版のコードから改良した点について

以前と比べ、何を改良したのかを軽く記述しておきます

  1. if (function_exists())で二重登録の防止
  2. グローバル変数$postの呼び出しをやめ、処理の冒頭でget_queried_object()を取得
  3. ページ種別の分岐方法や順番を改良
  4. 各ページ種別での出力コードを改良(特に投稿ページ)
  5. カスタム投稿タイプに紐づいたカスタムタクソノミーも表示
  6. ソースは変数に代入していくのではなく、その場でechoさせる
  7. 2019/8/31追記:エスケープ処理をちゃんと書いた

サイトに合わせて改良すべき部分

トップページで return する部分について

関数の冒頭でif ( is_front_page() ) return false; としていますが、ここは少し注意してほしいポイントです。

パンくずリストは「トップページ」では不要なのでこのようにしているのですが、「トップページ」を判別する方法は実は相当ややこしいです。

今回のコードでは【WordPressの「ホームページの表示」設定で「投稿ページ」だけを指定する】という特殊なパターンは考慮していませんので、その辺りはご注意ください。

なんのことだ???」となった方は以下の記事をご覧ください。

WordPressで「ホームページの表示」設定で最新の投稿・固定ページを指定した時のトップページの挙動の違いまとめ。

カスタム投稿タイプ・タクソノミーの部分

上記の改良点⑤の部分、「カスタム投稿タイプに紐づいたカスタムタクソノミー」を表示する部分ですが、仕様がはっきり固まっているサイトでは、それに合わせて改善していただいた方がいいかと思います。

例えば、「このサイトではこのカスタム投稿タイプしか使わない」・「このカスタム投稿タイプにはこのタクソノミーしかつかない」などと決まっている場合ですね。

is_single()での分岐の中で、カスタム投稿タイプに関してはさらにif($post_type !== 'post')として分岐していますが、ここを明示的にif($post_type === 'custom_type')のようにして、変数$the_taxを対応するタクソノミー名に固定してお使いするなどしてください。

関数でなくても可

そもそもの部分になってきますが、別に関数化してなくてもOKです。

テンプレートパーツとしてファイルに分けて、get_template_paert()で呼び出してももちろん大丈夫です。
この辺は自分が管理しやすい方でどうぞ!

関数にした方が「functions.phpにコピペして好きなとこで呼び出してね」って説明が楽なので、この記事ではそうしています。笑

パンくずリスト生成関数を呼び出す

さて、あとは好きな場所で関数を呼び出すだけでパンくずリストが設置されます。

パンくずリストを設置したい場所に以下のコードを記述

<?php custom_breadcrumb(); ?>

header.phpなどの共通パーツで呼び出すと一箇所の記述だけでいいので便利です。

JSON-LD対応版のパンくずリスト生成関数

一応、JSON-LD対応版のコードも紹介しておきます。

主要なページ(投稿ページ・固定ページ・カテゴリーやタグアーカイブ)でのみJSON-LDを生成しています。
全ページでは対応していないのでご了承ください。

if ( ! function_exists( 'custom_breadcrumb' ) ) {
  function custom_breadcrumb() {

    // トップページでは何も出力しないように
    if ( is_front_page() ) return false;

    //そのページのWPオブジェクトを取得
    $wp_obj = get_queried_object();

    //JSON-LD用のデータを保持する変数
    $json_array = array();

    echo '<div id="breadcrumb">'.  //id名などは任意で
      '<ul>'.
        '<li>'.
          '<a href="'. esc_url( home_url() ) .'"><span>ホーム</span></a>'.
        '</li>';

    if ( is_attachment() ) {

      /**
       * 添付ファイルページ ( $wp_obj : WP_Post )
       * ※ 添付ファイルページでは is_single() も true になるので先に分岐
       */
      $post_title = apply_filters( 'the_title', $wp_obj->post_title );
      echo '<li><span>'. esc_html( $post_title ) .'</span></li>';

    } elseif ( is_single() ) {

      /**
       * 投稿ページ ( $wp_obj : WP_Post )
       */
      $post_id    = $wp_obj->ID;
      $post_type  = $wp_obj->post_type;
      $post_title = apply_filters( 'the_title', $wp_obj->post_title );

      // カスタム投稿タイプかどうか
      if ( $post_type !== 'post' ) {

        $the_tax = "";  //そのサイトに合わせて投稿タイプごとに分岐させて明示的に指定してもよい

        // 投稿タイプに紐づいたタクソノミーを取得 (投稿フォーマットは除く)
        $tax_array = get_object_taxonomies( $post_type, 'names');
        foreach ($tax_array as $tax_name) {
            if ( $tax_name !== 'post_format' ) {
                $the_tax = $tax_name;
                break;
            }
        }

        $post_type_link = esc_url( get_post_type_archive_link( $post_type ) );
        $post_type_label = esc_html( get_post_type_object( $post_type )->label );

        //カスタム投稿タイプ名の表示
        echo '<li>'.
              '<a href="'. $post_type_link .'">'.
                '<span>'. $post_type_label .'</span>'.
              '</a>'.
            '</li>';

        //JSON-LDデータ
        $json_array[] = array(
          'id' => $post_type_link,
          'name' => $post_type_label
        );

        } else {

          $the_tax = 'category';  //通常の投稿の場合、カテゴリーを表示

        }

        // 投稿に紐づくタームを全て取得
        $terms = get_the_terms( $post_id, $the_tax );

        // タクソノミーが紐づいていれば表示
        if ( $terms !== false ) {

          $child_terms  = array();  // 子を持たないタームだけを集める配列
          $parents_list = array();  // 子を持つタームだけを集める配列

          //全タームの親IDを取得
          foreach ( $terms as $term ) {
            if ( $term->parent !== 0 ) {
              $parents_list[] = $term->parent;
            }
          }

          //親リストに含まれないタームのみ取得
          foreach ( $terms as $term ) {
            if ( ! in_array( $term->term_id, $parents_list ) ) {
              $child_terms[] = $term;
            }
          }

          // 最下層のターム配列から一つだけ取得
          $term = $child_terms[0];

          if ( $term->parent !== 0 ) {

            // 親タームのIDリストを取得
            $parent_array = array_reverse( get_ancestors( $term->term_id, $the_tax ) );

            foreach ( $parent_array as $parent_id ) {
              $parent_term = get_term( $parent_id, $the_tax );
              $parent_link = esc_url( get_term_link( $parent_id, $the_tax ) );
              $parent_name = esc_html( $parent_term->name );
              echo '<li>'.
                    '<a href="'. $parent_link .'">'.
                      '<span>'. $parent_name .'</span>'.
                    '</a>'.
                  '</li>';
              //JSON-LDデータ
              $json_array[] = array(
                'id' => $parent_link,
                'name' => $parent_name
              );
            }
          }

          $term_link = esc_url( get_term_link( $term->term_id, $the_tax ) );
          $term_name = esc_html( $term->name );
          // 最下層のタームを表示
          echo '<li>'.
                '<a href="'. $term_link .'">'.
                  '<span>'. $term_name .'</span>'.
                '</a>'.
              '</li>';
          //JSON-LDデータ
          $json_array[] = array(
            'id' => $term_link,
            'name' => $term_name
          );
        }

        // 投稿自身の表示
        echo '<li><span>'. esc_html( strip_tags( $post_title ) ) .'</span></li>';

    } elseif ( is_page() || is_home() ) {

      /**
       * 固定ページ ( $wp_obj : WP_Post )
       */
      $page_id    = $wp_obj->ID;
      $page_title = apply_filters( 'the_title', $wp_obj->post_title );

      // 親ページがあれば順番に表示
      if ( $wp_obj->post_parent !== 0 ) {
        $parent_array = array_reverse( get_post_ancestors( $page_id ) );
        foreach( $parent_array as $parent_id ) {
          $parent_link = esc_url( get_permalink( $parent_id ) );
          $parent_name = esc_html( get_the_title( $parent_id ) );
          echo '<li>'.
                '<a href="'. $parent_link .'">'.
                  '<span>'. $parent_name .'</span>'.
                '</a>'.
              '</li>';
          //JSON-LDデータ
          $json_array[] = array(
            'id' => $parent_link,
            'name' => $parent_name
          );
        }
      }
      // 投稿自身の表示
      echo '<li><span>'. esc_html( strip_tags( $page_title ) ) .'</span></li>';

    } elseif ( is_post_type_archive() ) {

      /**
       * 投稿タイプアーカイブページ ( $wp_obj : WP_Post_Type )
       */
      echo '<li><span>'. esc_html( $wp_obj->label ) .'</span></li>';

    } elseif ( is_date() ) {

      /**
       * 日付アーカイブ ( $wp_obj : null )
       */
      $year  = get_query_var('year');
      $month = get_query_var('monthnum');
      $day   = get_query_var('day');

      if ( $day !== 0 ) {
        //日別アーカイブ
        echo '<li>'.
              '<a href="'. esc_url( get_year_link( $year ) ) .'"><span>'. esc_html( $year ) .'年</span></a>'.
            '</li>'.
            '<li>'.
              '<a href="'. esc_url( get_month_link( $year, $month ) ) . '"><span>'. esc_html( $month ) .'月</span></a>'.
            '</li>'.
            '<li>'.
              '<span>'. esc_html( $day ) .'日</span>'.
            '</li>';

      } elseif ( $month !== 0 ) {
        //月別アーカイブ
        echo '<li>'.
              '<a href="'. esc_url( get_year_link( $year ) ) .'"><span>'. esc_html( $year ) .'年</span></a>'.
            '</li>'.
            '<li>'.
              '<span>'. esc_html( $month ) .'月</span>'.
            '</li>';

      } else {
        //年別アーカイブ
        echo '<li><span>'. esc_html( $year ) .'年</span></li>';

      }

    } elseif ( is_author() ) {

      /**
       * 投稿者アーカイブ ( $wp_obj : WP_User )
       */
      echo '<li><span>'. esc_html( $wp_obj->display_name ) .' の執筆記事</span></li>';

    } elseif ( is_archive() ) {

      /**
       * タームアーカイブ ( $wp_obj : WP_Term )
       */
      $term_id   = $wp_obj->term_id;
      $term_name = $wp_obj->name;
      $tax_name  = $wp_obj->taxonomy;

      /* ここでタクソノミーに紐づくカスタム投稿タイプを出力しても良いでしょう。 */

      // 親ページがあれば順番に表示
      if ( $wp_obj->parent !== 0 ) {

        $parent_array = array_reverse( get_ancestors( $term_id, $tax_name ) );
        foreach( $parent_array as $parent_id ) {
          $parent_term = get_term( $parent_id, $tax_name );
          $parent_link = esc_url( get_term_link( $parent_id, $tax_name ) );
          $parent_name = esc_html( $parent_term->name );
          echo '<li>'.
                '<a href="'. $parent_link .'">'.
                  '<span>'. $parent_name .'</span>'.
                '</a>'.
              '</li>';
          //JSON-LDデータ
          $json_array[] = array(
            'id' => $parent_link,
            'name' => $parent_name
          );
        }
      }

      // ターム自身の表示
      echo '<li>'.
            '<span>'. esc_html( $term_name ) .'</span>'.
          '</li>';


    } elseif ( is_search() ) {

      /**
       * 検索結果ページ
       */
      echo '<li><span>「'. esc_html( get_search_query() ) .'」で検索した結果</span></li>';

    
    } elseif ( is_404() ) {

      /**
       * 404ページ
       */
      echo '<li><span>お探しの記事は見つかりませんでした。</span></li>';

    } else {

      /**
       * その他のページ(無いと思うけど一応)
       */
      echo '<li><span>'. esc_html( get_the_title() ) .'</span></li>';

    }

    echo '</ul>';
    
    //JSON-LDの出力(2階層以上であれば)
    if ( !empty( $json_array ) ) :
      $pos = 1;
      $json = '';
      foreach ( $json_array as $data ) : 
        $json .= '{
          "@type": "ListItem",
          "position": '. $pos++ .',
          "item": {
              "@id": "'. $data['id'] .'",
              "name": "'. $data['name'] .'"
          }
        },';
      endforeach;

      echo '<script type="application/ld+json">{
        "@context": "http://schema.org",
        "@type": "BreadcrumbList",
        "itemListElement": ['. rtrim( $json, ',' ) .']
      }</script>';
      endif;

    echo '</div>';  // 冒頭に合わせた閉じタグ

  }
}

json-ldを生成する位置はとりあえず「パンくずリスト」でまとめれるように大枠のdivタグの中に仕込んでいますが、好きな場所に出すようにカスタマイズしてお使いください。

パンくずリスト生成関数は、WordPressの勉強に最適だった

今回ご紹介したコードは、あくまで私が個人的に納得するところまで考えたものです。
ご自身の手で、もっと効率的に改良したり、余裕のある人は一からコードを考えてみてください。

パンくずリストを適切に生成させるにはWordPressのあらゆるページについての知識が必要なので、すごく勉強になりますよ。

そして、定期的にコードのメンテナンスをしてみましょう。

あとで見直した時に「なんだよこのコード!めちゃくちゃ非効率じゃねぇか」って思うことができれば、その分プログラミングの知識がついた、ということも実感できるのではないかと思います!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメント一覧 (8件)

  • こんばんは
    とても参考になりました!
    ありがとうございます。

    一個指摘でスキーマの方のパンくずリストでspanの閉じタグが誤っている場所がありました。
    年</span.

  • こんばんは。
    参考にさせていただきともて重宝しております。ありがとうございます。
    タイトル内に記述されているなどのhtmlタグを、パンくずのみ削除するには、どのようにしたらよろしいでしょうか。

  • こちらのソースそのまま使えました!とても助かりました。ありがとうございます!

  • コピペで使えました。ありがとうございます!

    「ホーム>ブログ」のように「>」で区切りたかったのですが、
    phpの知識が浅いため下手にいじれず、下記のCSSで対処してみました。
    うまくいって満足ですw

    #breadcrumb ul li a:after {
    content: “>”;
    }

  • 2年前の更新記事ですがコメント失礼します。
    そのまま使えそうでしたので、使わせていただきました。
    固定ページに使用させていただいたのですが、json-ldが出力されません。
    知識が乏しいため教えていただけるとありがたいのですが、処理がうまくいった場合json-ldはどの位置に出力されるのでしょうか?
    開発者モードで「」等、echo以下の文を検索しているのですが、ヒットしません。

  • たびたびすみません。
    2階層以上の場合というのを見逃していました。
    2階層あるページで確認したところ、きちんと出力されているのが確認できました。

    プラグインではしたいようにカスタマイズできなかったため、コードを共有していただいてとても助かりました。
    ありがとうございました。

目次