ACFの値が出力されない・空になる原因と対処法

Advanced Custom Fields(ACF)は、カスタムフィールドを扱う定番プラグインです。管理画面で入力欄を作り、テンプレートで the_field() や get_field() を呼ぶだけで値を出力できます。ところが実際の制作では、「入力したのに表示されない」「空の値が返ってくる」という声がよく挙がります。

この記事では、ACFの値が出力されないときの原因を、パターン別に整理して解説します。原因が分かれば、ほとんどは数分で解決できます。

まず確認:正しい基本の書き方

最初に、基本の呼び出し方を確認します。

<?php
// 値を取得して変数に入れる
$text = get_field( 'catch_copy' );
if ( $text ) {
	echo esc_html( $text );
}

// その場で出力する
the_field( 'catch_copy' );
?>

get_field() は値を返し、the_field() は値をそのまま出力します。出力前のチェックや加工が必要なときは、get_field()を使うのが基本です。この2つの使い分けを間違えて、echo the_field() と書いてしまうこともありますが、the_field() はそれ自体が出力するため、冗長です。

原因1:フィールド名とフィールドキーの取り違え

ACFには、フィールドの「ラベル」「名前」「キー」という3つの識別子があります。

  • ラベル:管理画面に表示される名前(日本語でも可)。コードでは使えない。
  • 名前:コードで指定する名前(例:catch_copy)。
  • キー:ACFが内部で使うID(例:field_65a1b2c3d4e5f)。

get_field()には、ラベルではなく「名前」を渡します。日本語のラベルを指定していたり、スペルが1文字違っていたりすると、値は取得できません。フィールドグループの編集画面で、名前の欄をコピーして貼り付けるのが確実です。

原因2:投稿IDが合っていない

get_field()は、デフォルトでは「現在のループ中の投稿」の値を取得します。ループの外で使ったり、別の投稿の値が必要だったりするときは、第2引数でIDを指定する必要があります。

// 特定の投稿IDを指定する
$value = get_field( 'catch_copy', 123 );

// 固定ページ「トップ」の値をどこからでも取得する
$front_id = get_option( 'page_on_front' );
$value    = get_field( 'catch_copy', $front_id );

よくあるのが、サブクエリのループ後に、ID指定なしで呼んでいるケースです。wp_reset_postdata() を忘れたままだと、サブクエリの最後の投稿の値が返ってきたり、空になったりします。また、アーカイブページでは、現在のページ自体は「投稿」ではないため、アーカイブ用の値は別途指定が必要です。

タームやユーザーの値を取得する場合

タクソノミーのターム、ユーザー、オプションページの値は、第2引数に専用の形式で渡します。

// タームのフィールド
$term = get_queried_object();
$value = get_field( 'term_color', $term );

// 別の指定方法
$value = get_field( 'term_color', 'category_5' );

// ユーザーのフィールド
$value = get_field( 'phone', 'user_1' );

// オプションページのフィールド
$value = get_field( 'footer_text', 'option' );

タームの場合の category_5 のような指定は、「タクソノミー名_ターム ID」の形式です。この形式を間違えると、空になります。

原因3:リピーターフィールドのループの書き方

リピーターフィールドは、通常のフィールドと取得方法が異なります。値を一括で取得するのではなく、行ごとにループします。

<?php if ( have_rows( 'staff_list' ) ) : ?>
	<ul>
	<?php while ( have_rows( 'staff_list' ) ) : the_row(); ?>
		<li>
			<?php the_sub_field( 'name' ); ?>
			(<?php the_sub_field( 'role' ); ?>)
		</li>
	<?php endwhile; ?>
	</ul>
<?php endif; ?>

ここで、次の点に注意してください。

  • ループの中では、get_field() ではなく get_sub_field() / the_sub_field() を使う
  • 入れ子(リピーターの中のリピーター)では、内側も have_rows() でループする
  • ループの外から子の値を取りたいときは、get_field( 'staff_list' ) で配列として取得してから、foreachで処理する

配列として取得する方法も覚えておくと、並べ替えや件数のカウントなど、柔軟な処理ができます。

$rows = get_field( 'staff_list' );
if ( $rows ) {
	foreach ( $rows as $row ) {
		echo esc_html( $row['name'] );
	}
}

原因4:戻り値の形式が想定と違う

画像、ファイル、リンク、投稿オブジェクトなどのフィールドは、「戻り値」の形式を設定できます。この設定と、テンプレートでの扱い方が合っていないと、何も表示されません。

画像フィールドの場合

  • 画像配列:配列で返る。$image['url'] のように使う。
  • 画像URL:URL文字列で返る。そのまま src に使える。
  • 画像ID:数値で返る。wp_get_attachment_image() などと組み合わせる。

戻り値が「配列」なのに <img src="<?php the_field( 'photo' ); ?>"> と書くと、「Array」と出力されてしまいます。逆に、戻り値が「URL」なのに $image['url'] と書くと、PHPの警告やエラー(PHP 8以降は致命的エラー)になります。

$image = get_field( 'photo' ); // 戻り値:画像配列の場合
if ( $image ) {
	echo '<img src="' . esc_url( $image['sizes']['medium'] ) . '" alt="' . esc_attr( $image['alt'] ) . '">';
}

フィールドグループの設定画面で「戻り値」を確認し、書き方を合わせてください。迷ったときは、var_dump( get_field( 'photo' ) ) で中身を見るのが早道です。

リンクフィールドの場合

リンクフィールドは、配列で返る場合は url・title・target の3つを持ちます。新しいタブで開く設定の target を忘れずに出力しましょう。

原因5:フィールドグループの表示条件が合っていない

編集画面で入力欄が表示されなければ、そもそも値を保存できません。フィールドグループの「表示条件」が、対象の投稿タイプ、テンプレート、カテゴリーなどと一致しているか確認してください。

  • ページテンプレートを条件にしている場合、テンプレートを選択して保存するまで、入力欄が出ない
  • カスタム投稿タイプを追加したのに、条件を更新していない
  • フィールドグループが「無効」状態になっている

また、フィールド名を途中で変更すると、既存の投稿には旧名で保存された値が残るため、新しい名前では空になります。既存の投稿の値を入力し直すか、データを移行する必要があります。

原因6:プレビューや下書きで値が出ない

公開前のプレビューでは、保存済みの最新の値が反映されないことがあります。特に、リビジョン機能とACFの組み合わせでは、プレビュー時に過去の値が表示されたり、空になったりすることがあります。

この場合は、プレビューではなく、一度「更新」を押して公開状態で確認するか、ACFのバージョンを最新にして改善されるか試してください。

原因7:キャッシュと出力のエスケープ

最後に、意外と見落とすのがキャッシュです。

  • ページキャッシュ系のプラグインが、古い表示を返している
  • オブジェクトキャッシュ(Redisなど)が、古い値を保持している

キャッシュをクリアして表示が変わるなら、原因はACFではなくキャッシュです。また、値がHTMLタグを含む場合に esc_html() で出力すると、タグが文字として表示されます。WYSIWYGフィールドの値はHTMLを含むため、wp_kses_post() を通して出力するなど、フィールドの種類に合わせたエスケープを選んでください。なお、the_field() は echo get_field() と同じで、自動ではエスケープされません。

デバッグの進め方

原因が分からないときは、次の順番で確認します。

  1. var_dump( get_field( 'フィールド名', 投稿ID ) ) で、実際の戻り値を確認する
  2. 値が NULL や false なら、フィールド名・投稿IDを疑う
  3. 値が Array なら、戻り値の形式と、書き方が合っているか確認する
  4. 管理画面の編集画面で、実際に値が保存されているか確認する
  5. キャッシュを無効にして、再度確認する

「何が返ってきているか」を見れば、原因の見当は、ほぼつきます。推測でコードを書き直す前に、まず値の中身を確認する癖をつけましょう。

まとめ

ACFの値が出力されない原因は、次の7つのどれかに当てはまることがほとんどです。

  • ラベルではなく、フィールドの「名前」を指定する
  • ループの外やサブクエリ後は、投稿IDを明示する(ターム・ユーザー・オプションは専用の形式で指定)
  • リピーターは、have_rows()とget_sub_field()でループする
  • 画像などは、戻り値の形式に合わせた書き方にする
  • フィールドグループの表示条件を確認する
  • プレビューでは、最新の値が出ないことがある
  • キャッシュと、エスケープ関数の選び方を確認する

まずは var_dump() で中身を見る。この一手が、最短の解決につながります。

PR当サイトはアフィリエイト広告を利用しています。掲載内容は広告主から依頼・指示を受けたものではなく、筆者の調査・体験にもとづきます。

コメント

タイトルとURLをコピーしました