ACFのリピーターフィールドで複数データを扱うときの落とし穴|現場で使える実践テクニック
こんにちは!
今日は「ACFのリピーターフィールドで複数データを扱うときの落とし穴」について解説します。
リピーターフィールドってそもそも何?
ACFのリピーターフィールドって、僕も最初めっちゃ便利だと思ったんですよ。
複数のデータセットを好きなだけ追加できて、編集画面も直感的で。
でも現場で使ってると、あることに気づくんです。
「あれ、これで大丈夫?」ってなることが、ほんま多い。
リピーターフィールドは、簡単に言うと「同じ構造のデータを何個でも繰り返して登録できるフィールド」です。
例えば、商品紹介ページで「商品の仕様情報」を複数件登録したいときとか、イベント情報で「タイムテーブル」を何個も追加したいときに使う。
めっちゃ便利なんですけど、この便利さゆえに設計を甘く見ると、後々コードが複雑になったり、クライアント更新が大変になったりするんです。
現場で見かける3つの設計ミス
ミス1: データ数の上限を決めずに設計
僕も昔やってしまったんですけど、クライアントに「何個でも追加できますよ!」って言うのは便利なようで、実は危険なんです。
なぜかというと、編集画面でスクロールしまくるようになるし、フロントエンドでも無限にデータをループ処理するコードになってしまう。
現場あるあるなんですけど、こういう場合ありませんか?
- 「こんなに大量に登録するお客さんいないだろう」と思ってた→実は100件登録されてた
- 編集画面が重くなって、クライアントから「更新が遅い」と文句がくる
- フロントエンドで「最新5件だけ表示するつもりが、全件読み込まれてる」ことに後から気づく
ほんま、これらは避けたい。
だから最初の設計段階で、「最大何件までにする?」と必ずクライアントに確認しておくといいですよ。
ミス2: ネストされたリピーターの過度な使用
ACFには「リピーター内にリピーターを入れる」ってことができるんです。
これがめっちゃ便利に見えるんですけど、管理画面が複雑になるし、データベースから取得するときのコードも複雑になる。
例えば、「セクション」の中に「項目」があって、その「項目」の中に「詳細情報」がある…みたいな3階層構造にしちゃうと、後でアクセスするとき$field['section'][0]['item'][0]['detail']みたいなことになって、ほんま読みづらい。
僕の経験上、ネストは最大1階層(リピーター内に別のフィールドがある程度)に抑えておく方が無難です。
ミス3: リピーター内に「テキスト○個」を詰め込む
これ、本当によく見るミスなんです。
「商品情報」という1つのリピーターに、商品名、説明、価格、在庫、カテゴリー、タグ…みたいに、関係ないデータまで詰め込んじゃうパターン。
データベース設計の観点からいうと、これは「正規化されていない」状態です。
クライアント更新を考えたときに、「商品カテゴリーだけ一括変更したい」みたいな要件が出たときに、修正が難しくなるんです。
データベースの観点だけじゃなく、UXの観点でも編集画面がゴチャゴチャになって、間違い入力が増えたりします。
実践的な正しい使い方
設計段階でのチェックリスト
リピーターフィールドを使う前に、こんなことを確認するといいですよ。
- データ数の上限は決まってるか?
「最大20件まで」とか「通常3〜5件」とか、事前にクライアントと詰めておく。 - 本当にリピーターが必要か?
もしかして、別の投稿タイプの方がいいのでは?と考え直す。 - データの関連性は適切か?
入れようとしてるデータが、本当に同じグループでいいのか確認する。 - 取得側のコードは複雑にならないか?
テンプレートでhave_rows()のループが3階層以上になってないか想像してみる。
実装例:シンプルな「タイムテーブル」リピーター
例えば、イベントページのタイムテーブルを作る場合、こんな感じでいいですよ。
ACF設定(管理画面)
フィールドグループ: Event Details
フィールド: schedule (リピーターフィールド)
リピーター内のサブフィールド:
・time (テキスト) → 「10:00」
・title (テキスト) → 「オープニング」
・description (テキストエリア) → 説明文
・speaker (関連投稿) → スピーカーを別の投稿から選択
このときのポイントは、speakerのような「別の投稿」を参照するデータは、リピーター内に直接テキスト入力させるのではなく、post_objectやrelationshipで関連付けることです。
そうするとクライアント側でも管理しやすいし、後でスピーカー情報を一括変更したいってなったときも対応しやすい。
テンプレートでの取得
テンプレートファイル(例: template-parts/schedule.php)では、こんな感じで取得します。
if ( have_rows( 'schedule' ) ) :
while ( have_rows( 'schedule' ) ) : the_row();
$time = get_sub_field( 'time' );
$title = get_sub_field( 'title' );
$description = get_sub_field( 'description' );
$speaker_id = get_sub_field( 'speaker' );
endwhile;
endif;
ほんまシンプルで、後で修正するときも分かりやすいですよ。
クライアント更新を考慮した設計
「クライアント更新」を考えたリピーター設計は、本当に大事です。
クライアントが「明日から新しい情報に更新したい」ってなったときに、スムーズに対応できるかどうかで、その後の評判も変わってきます。
例えば、商品情報リピーターなら:
- 商品画像は「画像フィールド」で、各リピーター行で個別に設定できるようにする