カスタム投稿のパンくずが HOME だけになる:投稿タイプが増えても抜けない受け皿の書き方

広告WordPress・PHP を学べる本

Amazonのアソシエイトとして、WordPress functions.phpは適格販売により収入を得ています。

あるサイトで、コラムの記事のパンくずが「HOME」だけになっていました。

コラムは、カスタム投稿で作った投稿タイプです。

コラムの一覧のページも、同じく「HOME」だけでした。

この記事では、原因の見つけ方と、あとで投稿タイプが増えても抜けない書き方をまとめます。

どうなっていたか

ページ 画面のパンくず(前) あるべき形
コラムの記事 HOME HOME > コラム > 記事のタイトル
コラムの一覧 HOME HOME > コラム
事例の記事・固定ページ・お知らせ 正しく出ていた (そのまま)

おもしろいのは、SEO のプラグイン(All in One SEO)が出す構造化データのほうは、正しかったことです。

ページの HTML の中の BreadcrumbList(JSON-LD)には、「Home > コラム > タイトル」が入っていました。

抜けていたのは、画面に出るパンくずだけでした。

構造化データはプラグインが作り、画面のパンくずはテーマが作っているので、片方だけが抜けることがあります。

原因:種類ごとに分けて書いていて、コラムの分けがなかった

テーマのパンくずは、template-parts/breadcrumb.php の 1 つのファイルで作っています。

中は、ページの種類ごとに if と elseif で分けて書いてありました。

形だけを抜き出すと、次のようになります。

template-parts/breadcrumb.php(直す前の形・中身は省略)
<?php
// HOME はいつも出す
?>
<li>…HOME…</li>
<?php
if ( is_welcart_member_page() ) :
	// 会員のページ
elseif ( strpos( $_SERVER['REQUEST_URI'], '/archives/customer' ) !== false ) :
	// 事例(customer)
elseif ( is_post_type_archive( 'news' ) ) :
	// お知らせの一覧
elseif ( is_singular( 'news' ) ) :
	// お知らせの記事
elseif ( is_category() ) :
	// カテゴリー
	// …(タグ・検索・日付・ブログのトップ)
elseif ( is_page() ) :
	// 固定ページ
elseif ( is_singular( 'post' ) ) :
	// ふつうの投稿
elseif ( is_404() ) :
	// 404
endif;
// コラム(column)の分けがない → HOME だけで終わる
書き方 役目
is_page() 固定ページのとき
is_singular( 'post' ) ふつうの投稿の記事のとき。カスタム投稿の記事は入らない
is_singular( 'news' ) お知らせ(テーマが作ったカスタム投稿)の記事のとき
is_post_type_archive( 'news' ) お知らせの一覧のとき
$_SERVER['REQUEST_URI'] 事例は、URL に /archives/customer が入っているかで分けていた

テーマを買ったときからある種類(投稿・固定ページ・お知らせ)と、あとから足した事例は、分けが書いてありました。

コラムは、あとからプラグイン(Custom Post Type UI)の書き出しで足した種類で、パンくずの分けを足していませんでした。

そのため、コラムのページはどの elseif にも当たらず、最初の「HOME」だけで終わっていました。

直し方:分けの最後に「受け皿」を足す

コラムのための elseif ( is_singular( 'column' ) ) を足すこともできます。

ただ、それだと、次に投稿タイプを足したときに、また同じことが起きます。

そこで、上の分けのどれにも当たらなかった投稿タイプを、まとめて受け止める分けを足しました。

置き場所は、分けのいちばん最後(is_404() の前)です。

上の分けはそのまま残すので、今まで正しく出ていたページは変わりません。

template-parts/breadcrumb.php(足したところ)
<?php
// …(上の分けはそのまま)
elseif ( is_singular( 'post' ) ) :
	// ふつうの投稿(そのまま)

// ここから足した受け皿:上で分けていない投稿の種類
// 一覧:HOME > 種類の名前
elseif ( is_post_type_archive() ) :
	$breadcrumb_type = get_queried_object();
?>
			<li class="p-breadcrumb__item c-breadcrumb__item">
				<span itemprop="name"><?php echo esc_html( $breadcrumb_type && ! empty( $breadcrumb_type->label ) ? $breadcrumb_type->label : post_type_archive_title( '', false ) ); ?></span>
			</li>
<?php
// 記事:HOME > 種類の名前(一覧があればリンク)> タイトル
elseif ( is_singular() && ( $breadcrumb_type = get_post_type_object( get_post_type() ) ) ) :
	$breadcrumb_type_link = $breadcrumb_type->has_archive ? get_post_type_archive_link( $breadcrumb_type->name ) : '';
	if ( $breadcrumb_type_link ) :
?>
			<li class="p-breadcrumb__item c-breadcrumb__item" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
				<a href="<?php echo esc_url( $breadcrumb_type_link ); ?>" itemscope itemtype="http://schema.org/Thing" itemprop="item">
					<span itemprop="name"><?php echo esc_html( $breadcrumb_type->label ); ?></span>
				</a>
				<meta itemprop="position" content="<?php echo $breadcrumb_position++; ?>" />
			</li>
<?php
	endif;
?>
			<li class="p-breadcrumb__item c-breadcrumb__item">
				<span itemprop="name"><?php echo strip_tags( get_the_title( $post->ID ) ); ?></span>
			</li>
<?php
// ここまで

elseif ( is_404() ) :
	// 404(そのまま)
endif;
書き方 役目
is_post_type_archive() 種類を指定しないと、どの種類の一覧でも当たる
get_queried_object() 一覧のページでは、その投稿タイプの情報(WP_Post_Type)が返る
->label 投稿タイプの名前(ここでは「コラム」)。登録のときに付けた名前がそのまま出る
post_type_archive_title( '', false ) 名前が取れなかったときの代わり。false で、出さずに文字で返す
is_singular() 種類を指定しないと、どの種類の記事でも当たる
get_post_type_object( get_post_type() ) 今の記事の投稿タイプの情報。取れないときは受け皿に入らない
->has_archive その種類に一覧のページがあるか
get_post_type_archive_link() 一覧のページの URL。一覧があるときだけ、種類の名前をリンクにする
esc_html()・esc_url() 画面に出す文字と URL を、安全な形にする

一覧のない種類は、種類の名前を出さない

投稿タイプには、一覧のページがないもの(has_archive が false)もあります。

たとえば、添付ファイル(メディア)の種類です。

リンク先のない「種類の名前」を出しても、押せないだけなので、その場合は「HOME > タイトル」にしました。

受け皿は最後に置く

is_singular() は、固定ページやふつうの投稿でも当たります。

もし上のほうに置くと、固定ページやお知らせまで受け皿に入ってしまい、今の出し方が変わります。

いちばん最後に置けば、上で分けたページは今まで通りで、分けていないページだけが受け皿に入ります。

テーマの見た目に合わせるため、<li> の class や、構造化データの属性(itemprop など)は、上の分けと同じ書き方にそろえました。

確かめた結果

このサイトの作業環境(WordPress 7.1.3・PHP 8.3.32)で確かめました。

テーマのファイルは変えずに、直す前のファイルを git から取り出して、試しのスクリプトから読ませて比べました。

DB には書いていません。

試しのスクリプト(要点だけ)
<?php
// 試しのスクリプト:URL の形でクエリを作り、直す前と後のパンくずを出して比べる
// 直す前のファイルは git show で取り出して、スクリプトの横に置いた(テーマのファイルは変えない)
$_SERVER['REQUEST_URI'] = $argv[1];
$_SERVER['HTTP_HOST']   = '(作業環境のホスト名)';
define( 'WP_USE_THEMES', false );
require '(作業環境の WordPress)/wp-load.php';
wp(); // URL からクエリを作る(is_singular() などが使えるようになる)

function bc_render( $file ) {
	global $post, $dp_options;
	ob_start();
	include $file;
	return ob_get_clean();
}
$before = bc_render( __DIR__ . '/breadcrumb-before.php' );
$after  = bc_render( get_template_directory() . '/template-parts/breadcrumb.php' );
// それぞれの <li> の文字とリンクを取り出して並べる
書き方 役目
WP_USE_THEMES を false WordPress とテーマの関数は読み込むが、ページは出さない
wp() REQUEST_URI の URL から、表示のときと同じクエリを作る
ob_start()・ob_get_clean() パンくずのファイルが出す HTML を、文字として受け取る

ページごとの前と後

ページ 直す前 直した後
コラムの記事 HOME HOME > コラム(一覧へのリンク)> 記事のタイトル
コラムの一覧 HOME HOME > コラム
事例の記事 HOME > 事例一覧 > タイトル 同じ
事例の一覧 HOME > 事例一覧 同じ
固定ページ HOME > ページのタイトル 同じ
お知らせの記事 HOME > お知らせ > タイトル 同じ
お知らせの一覧 HOME > お知らせ 同じ
ふつうの投稿 HOME > カテゴリー > タイトル 同じ
404 のページ HOME > 見つからないという文 同じ

変わったのはコラムの 2 種類だけで、ほかのページは、前と後で文字もリンクも同じでした。

コラムの記事 すべて

公開中のコラムの記事 62 件を、1 件ずつ同じ方法で比べました。

直す前 直した後
HOME だけ 62 0
HOME > コラム > タイトル 0 62

一覧のない種類(添付ファイル)

添付ファイルのページも、試しのスクリプトで比べました。

添付ファイルの親 直す前 直した後
コラムの記事 HOME HOME > ファイルのタイトル
ふつうの投稿 HOME HOME > ファイルのタイトル
固定ページ HOME > ファイルのタイトル 同じ

一覧がないので、「添付ファイル」という種類の名前は出ず、「HOME > タイトル」になりました。

固定ページの下の添付ファイルは、is_page() にも当たるため、受け皿の前の固定ページの分けで出ていて、変わりませんでした。

なお、このサイトは添付ファイルのページを開かない設定(wp_attachment_pages_enabled が 0)なので、実際に開くと画像のファイルへ移ります(301)。

そのため、添付ファイルのパンくずは、試しのスクリプトの中だけで確かめました。

画面と構造化データ

直したあとのページを開いて、画面のパンくずと、HTML の中の BreadcrumbList を比べました。

ページ 画面のパンくず BreadcrumbList(JSON-LD)
コラムの記事(作業環境) HOME > コラム > タイトル Home > コラム > タイトル
コラムの記事(本番) HOME > コラム > タイトル Home > コラム > タイトル
コラムの一覧(作業環境) HOME > コラム Home > Archives for (名前が空)
コラムの一覧(本番) HOME > コラム Home > Archives for (名前が空)

記事のページは、画面と構造化データの並びがそろいました。

一覧のページでは、プラグインの構造化データの 2 つ目の名前が「Archives for 」のあとが空になっていました。

これはプラグインが作る部分で、テーマのパンくずとは別です。

この記事では直していません(原因も調べていません)。

あとで投稿タイプを新しく足したときの動きは、このサイトではまだ種類を足していないので、試していません。

受け皿の書き方は種類の名前を書いていないので、コラムと同じように出るはずです。

気をつけること

  • 受け皿は、分けのいちばん最後に置きます。上に置くと、今まで正しく出ていたページの形が変わります
  • 種類の名前は、投稿タイプを登録したときの名前(label)がそのまま出ます。英語の名前で登録していれば、英語で出ます
  • パンくずのファイルを直す前に、構造化データ(JSON-LD)がどうなっているかも見ておくと、どちらが抜けているかが分かります
  • テーマを更新すると、パンくずのファイルが元に戻ることがあります。子テーマや、自分で管理しているテーマで直します

まとめ

  • カスタム投稿のパンくずが HOME だけになるのは、テーマが種類ごとに分けて書いていて、その種類の分けがないことが多い
  • 種類を 1 つずつ足す代わりに、is_post_type_archive() と is_singular() を種類なしで使う受け皿を、分けの最後に置く
  • 種類の名前は get_post_type_object() の label、一覧へのリンクは has_archive があるときだけ get_post_type_archive_link() で出す
  • 直す前のファイルを git から取り出して、試しのスクリプトで前と後を並べると、変わったページと変わらないページがはっきり分かる
  • 画面のパンくずと、プラグインの構造化データは別に作られているので、両方を見る

参考

関連機能

  1. WordPress SiteGuard プラグインにて入力を間違えて管理者アカウントがログインロック状態になった場合の解除方法

  2. WordPress 「現在メンテナンス中のため、しばらくの間ご利用いただけません。」画面を解除する方法

  3. WordPress Simply Staticプラグインを使用している際に code 429 Too Many Requestsが発生

サイドバー

よく使うカスタマイズ

最近の記事

Profile

PAGE TOP