Cocoonでカスタム投稿タイプのパンくずリストとカテゴリ表示する方法

Cocoonでカスタム投稿タイプのパンくずリストとカテゴリ表示する方法
2023/8/8更新

出来るだけテンプレートファイルを触らない方向に修正したので、Cocoonのアップデートにも少し強くなりました。

Cocoonでサイト作成する機会があり、詰まったところがあったので備忘録として残しておきます。

やりたいことは、カスタム投稿タイプの追加した際の以下の問題点の改善。

  • カテゴリ(ターム名)が表示されない
  • パンくずリストが表示されない

今回、子テーマを編集することで問題を無事解決することができました。

この記事では、以下のようなメリットがあります。

  • パンくずリストやカテゴリ(親ターム・子ターム)の表示ができる
  • ほとんどの箇所をフックで関数のみ編集するのでアップデートに強い
  • 柔軟性を持たせて編集できる

カスタム投稿タイプは、プラグイン「Custom Post Type UI」を利用しました。

WordPressのおすすめサーバー

特徴
  • 料金が安い
  • WordPressが超高速
  • ドメイン永久無料
  • 安心の実績とサポート体制

新規も乗り換えも

目次

まず完成形がこちら

カスタム投稿タイプで、パンくずリスト、ターム(カテゴリ)ラベルが問題なく表示されています。

デザインはCSSで独自のカードタイプに調整しました。

カテゴリ別(ターム別)に分けて表示することも可能です。

新規をクリックした状態
その他をクリックした状態

投稿ページのパンくずリスト、ターム表示も問題ありません。

前提条件

前提条件として以下の構成で作成しています。

Cocoonバージョン: 2.6.4(2023/8/8時点最新)
PHP8系エラーなし

カスタム投稿タイプの設定

Custom Post Type UIで以下のように設定しました。

追加項目ラベルスラッグ
カスタム投稿タイプ制作実績works
カスタムタクソノミー制作ジャンルgenre

今回は、こちらのスラッグを元に作成しています。

プラグインの使い方は省略しますが、投稿タイプの追加と編集で「アーカイブあり」が“偽”になっていると一覧は表示されませんので“真”にしておきます

その他

  • パンくずリストは「メインカラム手前」に設置
  • 全て子テーマ側を編集

便宜上、以下のように表記揺れがあることをご了承ください。

  • 一覧ページ=アーカイブページ
  • 投稿ページ=個別記事ページ
  • カテゴリ=タクソノミー
  • カスタム分類=カスタムタクソノミー

ページの作成

ざっくり流れを説明すると、以下のファイルを親テーマから子テーマにコピーし、名称変更するといった内容になります。

  • single.php → single-works.php(投稿ページ用)
  • index.php → archive-works.php(一覧ページ用)
  • index.php → taxonomy-genre.php(カスタム分類ページ用)

※青字はスラッグ

投稿ページを作成

WordPressの決まり事として、投稿ページのテンプレートファイルには以下のような命名規則があります。

  • 投稿ページ:single.php
  • カスタム投稿ページ:single-(投稿タイプスラッグ).php

single.phpを子テーマにコピーして、single-(投稿タイプスラッグ).phpに名称変更することで、カスタム投稿ページに適用させます。

今回の場合は、single-works.phpとなります。

一覧ページを作成

Cocoonでカスタム投稿タイプのパンくずリストとカテゴリ表示

一覧ページにも、以下のような命名規則があります。

  • 一覧ページ:archive.php
  • カスタム投稿の一覧ページ:archive-(投稿タイプスラッグ).php

しかしCocoonにはarchive.phpの用意が無いので、代わりに使用されているindex.phpを子テーマにコピーします。

コピーしたindex.phparchive-(投稿タイプスラッグ).php名称変更することで、カスタム投稿タイプの一覧ページとして適用させます。

今回の場合は、archive-works.phpとなります。

命名規則と優先順位について

カスタム投稿タイプの場合には、まずarchive-(投稿タイプスラッグ).phpが適用されますが、存在しない場合は次に優先されるテンプレートがarchive.phpです。それでも存在しない場合は最終的にindex.phpという汎用テンプレートファイルが適用されます。このようにすべてのページにはテンプレート階層があり、最終的にはどのページでもindex.phpが適用されます。

カスタム分類ページの作成

Cocoonでカスタム投稿タイプのパンくずリストとカテゴリ表示

カテゴリ(分類)ページの命名規則は、以下のようになっています。

  • カテゴリページ:taxonomy.php(もしくはarchive.php)
  • カスタム分類ページ:taxsonomy-(タクソノミースラッグ).php

こちらもCocoonではindex.phpで表示されているため、同じように子テーマにコピーし、taxsonomy-(タクソノミースラッグ).phpと名称変更します。

今回の場合は、taxonomy-genre.phpとなります。

細かい編集と予備知識

子テーマもアップデートに対応させる

作成したテンプレートの中身を丸ごと以下のコードに置き換えることで、親テーマのテンプレートファイルをそのまま参照することができます。

single-works.phpの中身

<?php get_template_part('single'); // single.phpを参照

archive-works.php, taxonomy-genre.phpの中身

<?php get_template_part('index'); // index.phpを参照

こうすることで、アップデートによる機能の追加や変更があった場合でも、子テーマに反映させることができます。

今回のカスタマイズでは、ページのテンプレートファイルの構造を変更する必要はなく、アップデートに対応させておいた方がメリットが大きいので書き換えました。

テンプレートファイル内の構造を大きく変更したい場合や、フックで対処できない場合はこちらの方法は使えません。

現在どのテンプレートファイルが使われているか確認する方法

「Show Current Template」というプラグインを使うことで、現在表示されているページはどのテンプレートファイルが使われているのかを知ることができます。

有効化すると、管理バー(アドミンバー)に現在使われているテンプレートファイル名が表示されます。

一覧ページのタイトルを変更

各ページを作成しましたが、デフォルトだとタイトルが以下のようになっています。

  • カスタム投稿タイプの一覧ページ:Archive
  • カスタム分類の一覧ページ:ターム名

タイトルの書き換えは、functions.phpに以下のコードを記述します。

//カスタム投稿タイプのタイトルを変更
function custom_archive_title( $title ){
  if ( is_post_type_archive() || is_tax()) {
    // スラッグを出力(ラベルを出力する場合->label)
    $title = (get_post_type_object(get_post_type())->name);
  }
return $title;
}
add_filter( 'get_archive_chapter_title', 'custom_archive_title', 10 );

スラッグを出力する場合は全て小文字になるので、以下のようにCSSで最初の文字だけ大文字に変更しています。

/* アーカイブのタイトルを最初だけ大文字に変更 */
.archive-title {
	text-transform: capitalize;
}

以上で、タイトルを「Works」に変更することができました。

あると便利!
ターム別ナビゲーションの作成

これは必須ではありませんが、一覧ページのタイトルの下に、ターム別に表示させるためのナビゲーション(ジャンルナビ)を作成します。

例:以下のようなリンクです。

すべて ターム1 ターム2 ターム3

これがあるとワンクリックでターム別に表示することができて便利…!

functions.phpに以下のコードを書き加えます。

// カスタム投稿のジャンルナビ追加
function genre_nav() {
  ?><!-- カスタム投稿のアーカイブページ -->
  <?php if (is_post_type_archive('works')) : ?>
   <div class="genre-nav">
    <div class="genre-nav-link">
      <a class="is-active" href="<?php echo esc_url( get_post_type_archive_link( 'works' ) ); ?>">すべて</a>
    </div>
    <?php
    $genre_terms = get_terms( 'genre', array( 'hide_empty' => false, 'orderby'=> 'id', 'parent' => 0) );
    foreach ( $genre_terms as $genre_term ) :
    ?>
    <div class="genre-nav-link">
      <a href="<?php echo esc_url( get_term_link( $genre_term, 'genre' ) ); ?>"><?php echo esc_html( $genre_term->name ); ?></a>
    </div>
    <?php
    endforeach;
    ?>
  </div>
  <?php endif; ?>

  <!-- カスタムタクソノミーのアーカイブページ -->
  <?php if (is_tax('genre')) : ?>
  <div class="genre-nav">
    <div class="genre-nav-link">
      <a  href="<?php echo esc_url( get_post_type_archive_link( 'works' ) ); ?>">すべて</a>
    </div>
    <?php 
    $cat = get_queried_object();
    $cat_name = $cat -> name;
    $genre_terms = get_terms( 'genre', array( 'hide_empty' => false, 'orderby'=> 'id', 'parent' => 0) );
    foreach ( $genre_terms as $genre_term ) :
    ?>
    <div class="genre-nav-link">
      <a class="<?php if( $cat_name == esc_html( $genre_term->name ) ) {	echo "is-active";
      } ?>" href="<?php echo esc_url( get_term_link( $genre_term, 'genre' ) ); ?>"><?php echo esc_html( $genre_term->name ); ?></a>
      </div>
    <?php
    endforeach;
    ?>
  </div>
  <?php endif; ?><?php
}
add_action( 'get_template_part_tmp/list-index', 'genre_nav' );
add_action( 'get_template_part_tmp/list-tab-index', 'genre_nav' );
add_action( 'get_template_part_tmp/list-category', 'genre_nav' );
add_action( 'get_template_part_tmp/list-category-columns', 'genre_nav' );

1つ目(上)のHTMLコードはカスタム投稿のアーカイブページに表示するコードで、作成した全てのタームを自動で出力するようにしています。

2つ目(下)のHTMLコードはカスタムタクソノミーのアーカイブページに表示するコードで、同じく作成した全てのタームを出力し、現在のページと一致している場合にis-activeを付与するというものです。

これらのコードをgenre_nav()という関数に入れ、フックで記事一覧の上に出力するようにしています。

function genre_nav() {
  // 出力する内容
}
// 記事一覧の上に出力するフック
add_action( 'get_template_part_tmp/list-index', 'genre_nav' );
add_action( 'get_template_part_tmp/list-tab-index', 'genre_nav' );
add_action( 'get_template_part_tmp/list-category', 'genre_nav' );
add_action( 'get_template_part_tmp/list-category-columns', 'genre_nav' );
get_template_partはアクションフックとして使える

テンプレートの中にget_template_part($slug)が存在すると、get_template_part_{$slug}としてアクションフックが使えます。

cssのカスタマイズ例
/* ジャンルナビ */
.genre-nav {
	display: flex;
	gap: 16px;
	margin-top: 40px;
	margin-bottom: 60px;
	justify-content: center;
	white-space: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

@media screen and (max-width: 1023px) {
	.genre-nav {
	margin-top: 20px;
	margin-bottom: 30px;
	}
}

/* スクロールで左にはみ出さないように左寄せ */
@media screen and (max-width: 480px) {
	.genre-nav {
	justify-content: start;
	}
}

.genre-nav::-webkit-scrollbar {
	display: none;
}

.genre-nav-link a {
	color: #888;
	font-weight: bold;
	padding: 4px 20px;
	text-decoration: none;
	display: inline-block;
	border-bottom: 2px solid transparent;
	transition: border .3s, color .3s;
}

@media screen and (max-width: 480px) {
	.genre-nav-link {
		width: 100%;
	}
	
	.genre-nav-link a {
		font-size: 14px;
		margin-right: 0;
		margin-bottom: 8px;
		padding-left: 0;
		padding-right: 0;
		width: 100%;
		text-align: center;
	}
}

.genre-nav-link a:hover,
.genre-nav-link .is-active {
	border-bottom: 2px solid;
	color: #333;
}

カテゴリ(ターム)ラベルを表示させる

投稿ページにタームラベルを表示

カスタム投稿タイプの投稿ページ

投稿ページのカテゴリラベル(記事左下)は、get_the_category_links()という関数が使われています。

この関数ではカテゴリーのみ取得されるようになっていますが、タクソノミーも追加する形で上書きすれば、カテゴリーもタクソノミーも取得し出力されるようになります。

functions.phpに以下のコードを書き加えます。

// 投稿ページのカテゴリーリンクラベルにタクソノミーを追加
if ( !function_exists( 'get_the_category_links' ) ):
function get_the_category_links(){
  $categories = null;
  $taxonomies = [ 'category', 'genre' ]; // 取得するタクソノミー(categoryはデフォルト)
  foreach ( $taxonomies as $taxonomy_slug ){
    $terms = get_the_terms( get_the_ID(), $taxonomy_slug );
    if ($terms && !is_wp_error($terms)) {
      foreach($terms as $term){
        $style = null;
        $categories .= '<a class="cat-link cat-link-'.$term->term_id.'" href="'.get_term_link( $term->slug, $term->taxonomy ).'"'.$style.'><span class="fa fa-folder cat-icon tax-icon" aria-hidden="true"></span>'.$term->name.'</a>';
      }
    }
  }
  return $categories;
}
endif;

これでカテゴリラベルが表示されました。

一覧ページにタームラベルを表示

Cocoonでカスタム投稿タイプのパンくずリストとカテゴリ表示

アイキャッチ上にあるカテゴリーラベルにはget_the_nolink_categoryという関数が使われています。

こちらも同じくカテゴリーのみしか取得できないため、タクソノミーを取得できるよう追加し関数を上書きします。

functions.phpに以下のコードを追加します。

// 一覧ページのアイキャッチ上のカテゴリーラベルにタクソノミーを追加
if ( !function_exists( 'get_the_nolink_category' ) ):
function get_the_nolink_category($id = null, $is_visible = true){
  if ($id) {
    $categories = get_the_category($id);
    $genres = get_the_terms($id, 'genre'); // タクソノミー 'genre' を取得
  } else {
    $categories = get_the_category();
    $genres = get_the_terms(get_the_ID(), 'genre'); // 現在の投稿のタクソノミー 'genre' を取得
  }
  // $categories と $genres をマージする
  if ($genres && !is_wp_error($genres)) {
    $categories = array_merge($categories, $genres);
  }
	
  $display_class = null;
  if (!$is_visible) {
    return;
  }

  //メインカテゴリーが指定してある場合は該当カテゴリーを適用
  $category = isset($categories[0]) ? $categories[0] : null;
  $main_cat_id = get_the_page_main_category($id);
  if ($main_cat_id && in_category($main_cat_id, $id)) {
    $category = get_category($main_cat_id);
  }

  //カテゴリーラベル制御用のフック
  $category = apply_filters('get_the_nolink_category', $category, $categories);
  if (isset($category->term_id) && isset($category->name)) {
    return '<span class="cat-label cat-label-'.$category->term_id.$display_class.'">'.$category->name.'</span>';
  }
}
endif;

少し長いですが、get_the_nolink_categoryの変更点は以下の部分のみです。

if ($id) {
    $categories = get_the_category($id);
    $genres = get_the_terms($id, 'genre'); // タクソノミー 'genre' を取得
  } else {
    $categories = get_the_category();
    $genres = get_the_terms(get_the_ID(), 'genre'); // 現在の投稿のタクソノミー 'genre' を取得
  }
  // $categories と $genres をマージする
  if ($genres && !is_wp_error($genres)) {
    $categories = array_merge($categories, $genres);
  }

$genresを書き加え、$categoriesにマージ(結合)しています。

これにより、$categoriesには複数のタクソノミーが格納されます。

以上で、投稿ページと一覧ページにタームを表示することが出来ました。

パンくずリストを作成

今回の一番の難関です。

パンくずリストはtmp/breadcrumbs.phpを編集するしかないため、子テーマにtmpフォルダを作成し、親テーマからbreadcrumbs.phpをコピーします。

パンくずリストを出力する場所を編集

「メインカラム手前」にパンくずリストを表示させるには、get_template_part_tmp-user/main-beforeに対してフックを利用します。

functions.phpに以下のコードを追加。

// カスタム投稿タイプのアーカイブにパンくずリスト追加
function custom_breadcrumbs() {
	if ( is_tax() || is_post_type_archive()){
		get_template_part('tmp/breadcrumbs');
	}
}
add_action( 'get_template_part_tmp-user/main-before', 'custom_breadcrumbs' );

フックを利用すると好きな箇所にbreadcrumbs.phpを出力することができるので便利ですね。

出力位置を確かめるには、関数の中にecho '出力テストです';などと入力してプレビューを確認してみましょう。

breadcrumbs.phpを編集

次にbreadcrumbs.phpの中を編集します。

全体を囲っている最初の分岐(10行目)にis_tax(),is_post_type_archive()を追加します。

if (is_single_breadcrumbs_visible() && (is_single() || is_category() || is_tax() || is_post_type_archive())){

投稿ページの$cats書き換え

「投稿ページの場合」の$catsを丸ごと以下のコードに置き換えます。

// 「投稿ページの場合」の$cats(14行目)
$cats = get_the_category();
↓
$cats = [];
$taxonomies = ['category', 'genre'];
foreach ($taxonomies as $taxonomy) {
  $terms = get_the_terms($post->ID, $taxonomy);
  if ($terms && !is_wp_error($terms)) {
    $cats = array_merge($cats, $terms);
  }
}

投稿ページで使用されている$catsの値に、カテゴリーとタクソノミーをマージ(統合)して代入しています。

まれに、get_the_terms()に複数のタクソノミーを配列として渡しているのを見かけますが、これは正しくありません。

// 誤った例(get_the_termsの第2引数に配列は使えない)
$cat = get_the_terms($post->ID, array('category', 'genre'));

うまく変換して処理される場合もありますが、エラーの原因となるので文字列以外はNGです。

その他書き換え

タクソノミーに対応させるために、他の箇所も以下のように書き換えします。

// 「メインカテゴリーがない場合は先頭のカテゴリーを適用」の$cat
$cat = (is_single() && isset($cats[0])) ? $cats[0] : get_category(get_query_var("cat"));
↓
$cat = (is_single() && isset($cats[0])) ? $cats[0] : get_queried_object();

// 「カテゴリ情報の取得」の上の$par
$par = get_category($cat->parent);
↓
$par = get_term($cat->parent);

// 「カテゴリ情報の取得」の下の$par
$par = get_category($par->parent);
↓
$par = get_term($par->parent);

カスタム投稿タイプの一覧ページでは、親タームが存在せずエラーとなるので、以下のように編集する必要があります。

親ターム関連の$parからカテゴリーの順番入れ替えの$catsまで囲む形でカスタム投稿タイプの一覧ページを除外し、カテゴリ情報の取得$cats = array();を条件分岐の外側に持っていきます。

$count = 1;
//カテゴリ情報の取得
$cats = array();
if (!is_post_type_archive()) {
  $par = get_term($cat->parent);
  while($par && !is_wp_error($par) && $par->term_id != 0){
    $cats[] = $par;
    $par = get_term($par->parent);
  }
  //カテゴリーの順番入れ替え
  $cats = array_reverse($cats);
}

このようなコードになっていればOK。

現カテゴリーの出力を編集

「現カテゴリーの出力」の下に、以下のようにコードを追記します。

// 現カテゴリーの出力
// カスタム投稿タイプの出力
if(is_post_type_archive()){
  $cat_link = get_post_type_archive_link( get_post_type() );
  $cat_name = $cat->name;
} else {
// カスタム投稿タイプ以外の出力		
  $cat_link = get_category_link( $cat->term_id );
  $cat_name = $cat->name;
}

カスタム投稿の出力をラベルに変更したい場合は、$cat->name$cat->labelに置き換えることで対応可能です。

すぐ下のHTML内にあるタグも、上記の変数に置き換えて完了です。

esc_url(get_category_link($cat->term_id))
↓
esc_url($cat_link)

esc_html($cat->name)
↓
esc_html($cat_name)

パンくずの間に階層を追加

パンくずリストは表示されましたが、階層が分かりづらいので、間にカスタム投稿タイプの「パンくず」を追加したいと思います。

  • 現在:「ホーム > 新規」
  • 目標:「ホーム > 制作実績 > 新規」

「先祖カテゴリーの出力」の上に、以下のコードを書き加えます。

//パンくずの間にカスタム投稿タイプの階層を追加
if(is_tax() || is_single() && !is_singular('post')) {
  ++$count;
  $echo .= '<div class="breadcrumb-item" itemscope itemtype="https://schema.org/ListItem" itemprop="itemListElement"><span class="fa fa-folder fa-fw" aria-hidden="true"></span><a href="'.esc_url(get_post_type_archive_link( get_post_type() )).'" itemprop="item"><span itemprop="name" class="breadcrumb-caption">'.esc_html(get_post_type_object(get_post_type())->name).'</span></a><meta itemprop="position" content="'.$count.'" /><span class="sp"><span class="fa fa-angle-right" aria-hidden="true"></span></span></div>';
}
//先祖カテゴリーの出力

タクソノミーページとカスタム投稿タイプの投稿ページにのみ表示されます。

おまけ:タグ一覧に通常投稿とカスタム投稿を混ぜる

カスタム投稿タイプにも通常投稿にも東京という同じコアのタグをつけた場合、東京タグ一覧ページには通常の投稿しか表示されません。

functions.phpに以下のコードで、カスタム投稿タイプも混ぜて表示することが可能です。

// タグアーカイブをカスタム投稿タイプとまとめて表示
function my_main_query( $query ) {
  if ( is_admin() || ! $query->is_main_query() )
    return;

  if ( $query->is_category() || $query->is_tag() ) {
    $query->set( 'post_type', array( 'post', 'works' ) );
    return;
  }
}
add_action( 'pre_get_posts', 'my_main_query' );

array( 'post', 'post_type1' )post_type1にはカスタム投稿タイプのスラッグを入力します。

この方法は以下の記事で知りました。
(ありがとうございます)

カスタム投稿タイプのページ作成まとめ

Cocoonは元々カスタム投稿タイプの利用は想定されていないため、自身でカスタマイズする他ありません。

ググっても詳しいコードが出てこなかったために、自分で作成した次第です。

今回は

  • single-works.php→(投稿ページ用)
  • archive-works.php→(一覧ページ用)
  • taxonomy-genre.php→(カスタム分類ページ用)

と3つのカスタム投稿タイプのページを作成し、パンくずリストとターム(カテゴリ)表示させる方法を解説しました。

もしテーマの大型アップデートで、構造が変われば見直す必要があります。

もし、不備や気になること等あればコメントくださいませ。

カスタマイズを自分でしてみませんか?

「あの機能追加したいな」「もう少しここを調整したいな」と思ったらWeb制作のスクール「デイトラ」がおすすめです…!

カリキュラムは3ヶ月分ですが、受講生は卒業後もずっと見放題!常に最新のコンテンツに更新されるため、情報が古くなるなんてこともありません。

価格はどのコースも10万円前後と他のスクールに比べても格安です。
なのに副業・転職に十分なスキルが身につきます。

管理人

私はWeb制作とWebデザインを受講し、現在フリーランスWebデザイナーとなりました。

他にも様々なコースが充実しているので、身につけたいスキルがあったら是非覗いてみてください。

コースの一部をご紹介

よかったらシェアしてね!

コメント

コメントする

目次