2026年5月28日
2026年5月28日
WordPressのテーマで投稿一覧にカスタムフィールドを表示する方法
投稿一覧(ブログのトップ、カテゴリーやタグのアーカイブ、検索結果など)にカスタムフィールドの値を出すには、一覧を出力しているループの中で get_post_meta() を呼び、エスケープして表示します。クラシックテーマならテンプレートファイルを子テーマで上書き、ブロックテーマならクエリーループ内でブロックバインディングかショートコードを使うのが基本です。この記事では、両方の手順と、値が出ないときの確認方法を解説します。
前提:カスタムフィールドの値が保存されているか
最初に、表示したい値が投稿に保存されているかを確認します。ここでは例として、投稿ごとに「subtitle(サブタイトル)」と「reading_time(読了目安の分数)」というキーで値を入れている想定で進めます。
標準のカスタムフィールド欄を使う場合、ブロックエディターでは初期状態で非表示になっていることがあります。エディター右上のメニューから設定(環境設定)画面を開き、パネルの項目で「カスタムフィールド」を有効にすると、本文の下に入力欄が出ます。表記はWordPressのバージョンによって多少異なります。
Advanced Custom Fields(ACF)などのプラグインで項目を作っている場合も、データは同じく投稿メタとして保存されます。フィールド名(キー)を控えておいてください。なお、キーが「_」(アンダースコア)で始まるものは保護されたメタとして扱われ、標準のカスタムフィールド欄には表示されません。
クラシックテーマ:一覧テンプレートを子テーマで上書きする
どのファイルを編集するか
クラシックテーマで投稿一覧を出しているのは、テンプレート階層に沿って home.php・archive.php・category.php・search.php・index.php などです。多くのテーマは、これらのファイルの中で get_template_part() を使い、1件分の表示を template-parts 内の別ファイル(content.php など)に任せています。
1件分の表示ファイルが見つかったら、子テーマに同じフォルダ構成・同じファイル名でコピーします。get_template_part() は子テーマ側のファイルを優先して読み込むため、親テーマを触らずに一覧の表示だけを変えられます。どのファイルが使われているか分からないときは、Query Monitor プラグインを入れると、表示中のページで読み込まれたテンプレートを確認できます。
ループ内に表示コードを書く
コピーしたファイルの、タイトルや抜粋の近くに次のコードを追加します。
<?php
$subtitle = get_post_meta( get_the_ID(), 'subtitle', true );
$reading_time = get_post_meta( get_the_ID(), 'reading_time', true );
?>
<?php if ( '' !== $subtitle ) : ?>
<p class="entry-subtitle"><?php echo esc_html( $subtitle ); ?></p>
<?php endif; ?>
<?php if ( '' !== $reading_time ) : ?>
<p class="entry-reading-time">読了目安:<?php echo esc_html( absint( $reading_time ) ); ?>分</p>
<?php endif; ?>
get_post_meta() の第3引数に true を渡すと、値が1つの文字列で返ります。値が無い投稿では空文字が返るので、空のときは要素ごと出さないようにしておくと、空の段落やラベルだけが残る見た目の崩れを防げます。
出力時は esc_html() でエスケープします。カスタムフィールドは投稿者権限のユーザーも入力できるため、値をそのまま echo するのは避けてください。数値として扱う値は absint() などで整数に変換しておくと、想定外の文字列が混ざっても表示が崩れません。
一覧で get_post_meta() を何度も呼んで重くならないか
WP_Query は、初期設定で取得した投稿のメタ情報をまとめて読み込みキャッシュします(update_post_meta_cache が有効なため)。そのため、メインループや通常の WP_Query のループ内で get_post_meta() を呼んでも、1件ごとにデータベースへ問い合わせが発生するわけではありません。独自にクエリを書く際に update_post_meta_cache を false にしている場合は、この恩恵がなくなる点に注意してください。
ACF の関数を使う場合
ACF で作ったフィールドは、get_field() でも取得できます。日付や選択肢などのフィールドは、ACF の設定に応じて整形された値が返るのが利点です。
<?php
$subtitle = function_exists( 'get_field' ) ? get_field( 'subtitle' ) : '';
if ( $subtitle ) {
echo '<p class="entry-subtitle">' . esc_html( $subtitle ) . '</p>';
}
function_exists() で確認しているのは、ACF を停止したときにサイトが致命的エラーで止まるのを防ぐためです。the_field() で直接出力する方法もありますが、出力時のエスケープの扱いは ACF のバージョンによって変更されてきたため、get_field() で取り出して自分でエスケープする書き方のほうが挙動を把握しやすくなります。
ブロックテーマ:クエリーループに値を出す
ブロックテーマでは、投稿一覧はサイトエディターのテンプレート(「ブログのホーム」「アーカイブ」など)にある「クエリーループ」ブロックで作られています。クエリーループの「投稿テンプレート」の中は1件ごとに繰り返されるので、ここにカスタムフィールドを表示するブロックを置きます。
方法1:ブロックバインディング(Block Bindings API)
WordPress 6.5 以降では、段落・見出し・画像・ボタンといった一部のコアブロックの内容を、投稿メタに結び付けられます(2026年10月現在、対応ブロックや編集画面での操作方法はバージョンごとに拡充されています)。使うには、メタを REST API に公開する形で登録しておく必要があります。
<?php
// 子テーマの functions.php
add_action( 'init', function () {
register_post_meta( 'post', 'subtitle', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
) );
} );
登録後、投稿テンプレート内に段落ブロックを置き、コードエディターで次のようにバインディングを指定します。新しめのバージョンでは、ブロックの設定サイドバーから接続先を選べる場合もあります。
<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"core/post-meta","args":{"key":"subtitle"}}}}} -->
<p></p>
<!-- /wp:paragraph -->
この方法は表示用のPHPテンプレートが不要で、サイトエディター上で位置や装飾を調整できるのが利点です。一方、「値が空のときは非表示」「単位を付ける」といった加工はしにくいので、その場合は方法2を使います。
方法2:ショートコードで加工して出す
加工が必要な場合は、ショートコードを作って投稿テンプレート内に「ショートコード」ブロックで置きます。クエリーループの中では処理中の投稿が順に切り替わるため、get_the_ID() でその投稿のIDが取れます。
<?php
add_shortcode( 'reading_time', function () {
$minutes = absint( get_post_meta( get_the_ID(), 'reading_time', true ) );
if ( ! $minutes ) {
return '';
}
return '<p class="entry-reading-time">読了目安:' . esc_html( $minutes ) . '分</p>';
} );
ショートコードブロックに [reading_time] と入力すると、各投稿の値が一覧に表示されます。
値が表示されないときの確認ポイント
- キー名の綴り: 大文字・小文字やハイフンとアンダースコアの違いでも別のキーになります。ACF の場合は「フィールドラベル」ではなく「フィールド名」を使います。
- 編集したファイルが使われているか: 子テーマにコピーしたファイルのパスが親テーマと一致しているか、Query Monitor などで読み込まれたテンプレートを確認します。
- ブロックテーマでテンプレートが二重管理になっていないか: サイトエディターで一度保存したテンプレートは、データベース側の内容がファイルより優先されます。ファイルを編集しても変わらない場合は、サイトエディター側の変更を確認します。
- キャッシュ: ページキャッシュを使っている場合、ログアウト状態では古い一覧が出ることがあります。変更後はキャッシュを削除します。
- PHPエラー: 一覧の途中で表示が途切れる場合は、WP_DEBUG_LOG を有効にして wp-content/debug.log を確認します。
テンプレートや functions.php を編集する前には、対象ファイルのバックアップを取り、テスト環境があればそちらで先に試してください。
まとめ
- 投稿一覧にカスタムフィールドを出すには、ループ内で get_post_meta( get_the_ID(), 'キー', true ) を呼び、esc_html() などでエスケープして表示します。
- クラシックテーマでは、1件分の表示テンプレートを子テーマへ同じパスでコピーして編集します。
- ブロックテーマでは、クエリーループの投稿テンプレート内で、ブロックバインディング(WordPress 6.5 以降)かショートコードブロックを使います。
- 空の値の扱い、キー名の綴り、テンプレートの読み込み先、キャッシュを順に確認すると、表示されない原因を絞り込めます。