Cocoonでカスタム投稿タイプのパンくずリストとカテゴリ表示する方法
本来は子テーマにテンプレートファイルをコピーして編集する必要があるのですが、ほぼ関数の上書きのみで完結できるようにコードを見直しました。Cocoonのアップデートによる影響も最小限です。
Cocoonでサイト作成する機会があり、詰まったところがあったので備忘録として残しておきます。
やりたいことは、カスタム投稿タイプの追加した際の以下の問題点の改善。
- カテゴリ(ターム名)が表示されない
- パンくずリストが表示されない
今回、子テーマを編集することで問題を無事解決することができました。
この記事では、以下のようなメリットがあります。
- パンくずリストやカテゴリの表示ができる
- 柔軟性を持たせて編集できる
- カスタム投稿タイプのテンプレートファイル作成は不要
カスタム投稿タイプは、プラグイン「Custom Post Type UI」を利用しました。
まず完成形がこちら
※CSSで独自のカードタイプにしています。
カスタム投稿タイプで、パンくずリスト、ターム(カテゴリ)ラベルが問題なく表示されています。
カテゴリ別(ターム別)に分けて表示することも可能です。
投稿ページのパンくずリスト、ターム表示も問題ありません。
前提条件
前提条件として以下の構成で作成しています。
Cocoonバージョン: 2.7.3.5(2024/5/19時点最新)
PHP8系エラーなし
カスタム投稿タイプの設定
Custom Post Type UIで以下のように設定しました。
追加項目 | ラベル | スラッグ |
---|---|---|
カスタム投稿タイプ | 制作実績 | works |
カスタムタクソノミー | 制作ジャンル | genre |
今回は、こちらのスラッグを元に作成しています。
プラグインの使い方は省略しますが、投稿タイプの追加と編集で「アーカイブあり」がFalseになっていると一覧は表示されませんのでTrueにしておきます。
主なカスタマイズ(フック)
パーツの呼び出しで利用されるget_template_part($slug)
関数にはフックが用意されており、get_template_part_{$slug} のような形式でアクションフックを利用することができます。
またCocoonでは、get_template_part()
を拡張したcocoon_template_part()が実装されたのでこちらも利用しています。
その他
便宜上、以下のように表記揺れがあることをご了承ください。
- 一覧ページ=アーカイブページ
- 投稿ページ=個別記事ページ
- カテゴリー=タクソノミー
- カスタム分類=カスタムタクソノミー
一覧ページのタイトルを変更
カスタム投稿タイプを作成すると、一覧ページのタイトルが「Archives」になっており、カスタム分類ページのタイトルでは「ターム名」が表示されています。
任意のタイトル名に変更するために、get_archive_chapter_title()に対し書き換えを行います。
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 );
スラッグの出力では全て小文字になるため「Works」となるようCSSで調節。
/* アーカイブのタイトルを最初だけ大文字に変更 */
.archive-title {
text-transform: capitalize;
}
カテゴリー(ターム)ラベルを表示させる
投稿ページのカテゴリーラベル
投稿ページの記事左下にあるカテゴリーラベルは、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;
これでカテゴリラベルが表示されました。
一覧ページのカテゴリラベル
アイキャッチ上のカテゴリーラベルにはget_the_nolink_category()という関数が使われています。
こちらも同じくタクソノミーを追加する形に編集し、関数を上書きします。
functions.php
に以下のコードを追加します。
※4〜14行(ハイライト部分)が元々のコードからの変更点。
// 一覧ページのカテゴリーラベル(タクソノミーを追加)
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;
カスタムタクソノミー$genres
を書き加え、元々のカテゴリー$categories
とマージ(結合)しています。
これにより、$categories
には複数のタクソノミーが格納され、どちらの場合にも表示されるようになります。
パンくずリストを作成
パンくずリストは、デフォルトでカテゴリーページと投稿ページにしか表示されないようになっています。
カスタム投稿タイプのアーカイブページに対応させるためには、is_tax()
とis_post_type_archive()
を適切に書き加える必要があります。
パンくずリストを出力する場所を編集
Cocoon設定にある「パンくずリストの配置」の位置に応じて出力できるように、フックを利用して条件分岐させます。
functions.php
に以下のコードを追加。
// パンくずリストをカスタム投稿タイプで表示
// メインカラム手前
function main_before_breadcrumbs() {
if ((is_tax() || is_post_type_archive()) && is_single_breadcrumbs_position_main_before()) {
get_template_part('tmp/breadcrumbs');
}
}
add_action( 'get_template_part_tmp-user/main-before', 'main_before_breadcrumbs' );
// メインカラムトップ
function main_top_breadcrumbs() {
if ((is_tax() || is_post_type_archive()) && is_single_breadcrumbs_position_main_top()) {
get_template_part('tmp/breadcrumbs');
}
}
add_action( 'get_template_part_tmp/list', 'main_top_breadcrumbs' );
// メインカラムボトム
function main_bottom_breadcrumbs() {
if ((is_tax() || is_post_type_archive()) && is_single_breadcrumbs_position_main_bottom()) {
get_template_part('tmp/breadcrumbs');
}
}
add_action('cocoon_part_after__tmp/pagination', 'main_bottom_breadcrumbs');
上記コードは、必要箇所のみ記述しても構いません。
各フックポジションは以下の通り。
- メインカラム手前→
get_template_part_tmp-user/main-before
- メインカラムトップ→
get_template_part_tmp/list
- メインカラムボトム(デフォルト)→
cocoon_part_after__tmp/pagination
- フッター手前→
footer.php
を編集
「フッター手前」に関しては、アーカイブページで表示させるための適切なフックがありませんでしたので、footer.phpを子テーマにコピーして編集する必要があります。
breadcrumbs.phpを編集
一番の難関です。
パンくずリストを構成しているコードtmp/breadcrumbs.php
を編集するため、子テーマにtmp
フォルダを作成し、親テーマからbreadcrumbs.php
をコピーします。
functions.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
をwhile(…)の上に移動し、$par
からカテゴリーの順番入れ替えの$cats
まで囲む形でカスタム投稿タイプの一覧ページを除外します。
$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
echoしている下のHTML内のタグを、変数に置き換えて完了です。
esc_url(get_category_link($cat->term_id))
↓
esc_url($cat_link)
esc_html($cat->name)
↓
esc_html($cat_name)
パンくずの間に階層を追加
一応パンくずリストは表示されましたが、もう一手間。
階層が分かりづらいので、間にカスタム投稿タイプの「パンくず」を追加します。
- 現在:「ホーム > 新規」
- 目標:「ホーム > Works > 新規」
「先祖カテゴリーの出力」の上に、以下のコードを書き加えます。
//パンくずの間にカスタム投稿タイプの階層を追加
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>';
}
//先祖カテゴリーの出力
- スラッグを出力:get_post_type())->name
- ラベルを出力:get_post_type())->label
これで階層が必要な箇所にパンくずが追加されます。
その他のカスタム
あると便利!
ターム別ナビゲーションの作成
一覧ページのタイトルの下に、ターム別に表示させるためのナビゲーション(ジャンルナビ)を作成します。
例:以下のようなリンクです。
これがあるとワンクリックでターム別に表示することができて便利…!
このパーツをアクションフックで、カスタム投稿タイプの記事一覧ページに表示させるという具合になります。
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' );
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;
}
おまけ:タグ一覧に通常投稿とカスタム投稿を混ぜる
カスタム投稿タイプにも通常投稿にも東京
という同じコアのタグをつけた場合、東京タグ一覧ページには通常の投稿しか表示されません。
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は元々カスタム投稿タイプの利用は想定されていないため、自身でカスタマイズする他ありません。
ググっても詳しいコードが出てこなかったために、自分で作成した次第です。
アップデートによりもっと簡潔にできるようになった場合は、追記します。
もし、不備や気になること等あればコメントくださいませ。
おすすめWEBスクール
WEB制作やWEBデザインを学びたいなら、SNSでも話題の「デイトラ」がおすすめ!
どのコースも10万円前後と業界最安値で、副業や転職に向けて十分なスキルを身につけることができます。
\ クリックしてジャンプ! /
お気軽にコメントどうぞ