🔧

WP6.5から導入された Block Binding API を利用したカスタムフィールド案件のリプレイス

2024/05/01に公開

TL;DR

  • 既存サイトのカスタム投稿がACFなどで本文を利用していないカスタムフィールド案件のリプレイス
  • リプレイス後はブロックエディターを利用したい
  • Block Binding APIを利用した、一歩進んだカスタムフィールド製造業

前提条件

Advanced Custom fields の設定画面。Before画像などのカスタムフィールド設定が並ぶ
このような Advanced Custom Fields を利用したカスタムフィールド案件があります。
既存サイトでは本文を利用せずにカスタムフィールドのみを利用した条件分岐などで出力を行っていました。
これをリプレイスした場合に、既存コンテンツを引き継ぎつつ、新規投稿はブロックエディターで行いたいという需要があると思います。いえ、今後カスタムフィールドは可能な限り使わずブロックのみで構築していくべきだと思いますので、そのように対応するべきなのだと思います

既存サイトのコード

<?php
$construct_address = get_field('construct_address', $post->ID);
if($construct_address):?>
<section class="block">
<h4>施工住所</h4>
<?php echo $construct_address;?>
</section>
<?php endif;

こんな感じでカスタムフィールドがあれば、従来は get_post_meta() などでその値をそのまま出力したり、テキストエリアを反映したりしていたと思います。

Block Binding API を利用する

新規サイトではカスタムフィールドで利用するようなデータ構造はそのままに、ブロックに変換していきたいです。
WordPress 6.5 からは、Block Binding API という機能が追加されました。これを利用するとカスタムフィールドがブロックにmetadata として追加する事が出来ます。
まだコードエディターを用いた設定のみで、管理画面上には値が反映されず、入力画面も存在せず、フロントのみ値が反映されますがそのうちインターフェイスなどが整備されていくと予想されます。

早速、先ほどの箇所を Block Binding API を利用した設定にすると、以下のようになります。

  <!-- wp:simple-definition-list-blocks/term -->
    <dt class="wp-block-simple-definition-list-blocks-term">施工住所</dt>
    <!-- /wp:simple-definition-list-blocks/term -->

    <!-- wp:simple-definition-list-blocks/details-html -->
    <dd class="wp-block-simple-definition-list-blocks-details-html"><!-- wp:paragraph
      {
"metadata":{
  "bindings":{
    "content":{
      "source":"acf/field",
      "args":{
        "userId": 3,
        "key":"construct_address"
      }
    }
  }
}
  } -->
      <p></p>
      <!-- /wp:paragraph -->
    </dd>
    <!-- /wp:simple-definition-list-blocks/details-html -->

※上記はコアのパラグラフにmetadataを設定していますが、その外側は Simple Definition List Blocksというプラグインを利用したDLリストで構成しています。該当箇所は dd内にHTMLを入れられるようにして、パラグラフが入っている構成になっています(いつも大変お世話になってるプラグインです)

WordPress管理画面、投稿画面のキャプチャ。施工住所の下にブロックを選択するには/を入力という文字が出ており、文字入力箇所が設定されている
上記のキャプチャのように、管理画面上は何も値がありませんが、
表示画面のキャプチャ。先ほど空だった箇所に住所2という文字が反映されている
表示側は入力した文字列が反映されています。

これでカスタムフィールドをブロック内から出力する仕組みが一応整いました。
カスタムフィールドを用いた案件の場合、入力がなければHTMLを出力しないという注文が入ると思いますので、その対応をしつつ、本文にブロックを挿入します。

    $construct_address = get_field('construct_address', $post_id);
    if ($construct_address) {
        $output .= '
';

このように条件分岐しながら、出力を関数でまとめて、

$args = [
    'posts_per_page'    => -1,
    'post_type'        => 'case',
];
$the_query = new WP_Query($args);
if ($the_query->have_posts()) : while ($the_query->have_posts()) : $the_query->the_post();

        $post_id = $the_query->post->ID;
        $post_content = '';

        $post_content .= convertBlockBeforeAfter($post_id);
        $post_content .= convertBlockDetail($post_id);


        // 投稿内容を更新
        wp_update_post([
            'ID' => $post_id,
            'post_content' => $post_content,
        ]);


    endwhile;
else :
endif;
wp_reset_postdata();

とすれば、本文がブロックバージョンで作られたものに更新されます。

うまくいかなかった事

今回、

"source": "acf/field",

として、acf/field をソースに指定していますが、core/post-meta が公式的なソースになります。しかし画像の場合は postmeta の場合、画像ID の出力となり

"metadata":{
    "bindings":{
      "url":{
        "source": "core/post-meta",
          "args": {
            "userId": 3,
            "key": "before-img"
          }
      }
    }
  }

とするとうまく行きませんでした。
そのため、ACFの値を出力する設定に揃えています。

参考にしたサイト

以下参考にさせて頂きました。ありがとうございます!

ブロックバインディング API を使ってブロックにカスタムフィールド値を出力する方法
ブロックバリエーションを利用してカスタムフィールドを出力する方法
New Feature: The Block Bindings API
Introducing Block Bindings, part 1: connecting custom fields

Discussion