「商品ページの価格だけをカスタムフィールドで管理して、見た目は段落ブロックで整えたい」——このような要件は、これまで専用のカスタムブロックやショートコードを作って対応するのが定番でした。WordPress 6.5 で追加されたブロックバインディング(Block Bindings API)を使うと、既存の段落ブロックや画像ブロックの属性に、カスタムフィールドなどの動的な値を紐づけられます。この記事では、カスタムフィールドを段落に表示する基本形から、自作のデータソースを登録する方法までを解説します。
目次
ブロックバインディングとは
ブロックバインディングは、ブロックの属性(attribute)と外部のデータを結びつける仕組みです。たとえば段落ブロックの content 属性に「投稿メタの book_author の値」を割り当てておくと、フロントエンドの表示時にその値が差し込まれます。ブロック自体に文字列を保存するのではなく、「どこから値を取ってくるか」だけを保存するという考え方です。
これまで同じことをするには、render_callback を持つ動的ブロックを自作するか、本文にショートコードを書くしかありませんでした。前者はブロックを一から作る手間がかかり、後者は編集画面で完成形が見えません。ブロックバインディングなら、見た目の調整は既存のコアブロックの機能をそのまま使いながら、中身だけを動的にできます。文字サイズも配置も色も、いつもの段落ブロックの設定パネルで決められるわけです。
WordPress 本体には最初から2つのデータソースが登録されています。
| ソース名 | 内容 |
|---|---|
core/post-meta | 投稿のカスタムフィールド(投稿メタ)の値を差し込む |
core/pattern-overrides | 同期パターンの中で、この部分だけ個別に書き換えられるようにする |
この2つに加えて、自分で PHP からソースを登録することもできます。まずは core/post-meta を使った基本形から見ていきましょう。
バインディングできるブロックと属性
どのブロックのどの属性でもバインドできるわけではありません。ブロック側が __experimentalRole(現在の role: 'content')としてコンテンツ属性を宣言している必要があり、コアブロックでは次の組み合わせがサポートされています。
| ブロック | バインドできる属性 |
|---|---|
段落(core/paragraph) | content |
見出し(core/heading) | content |
画像(core/image) | url / alt / title |
ボタン(core/button) | text / url / linkTarget / rel |
対応ブロックは WordPress のバージョンが上がるにつれて増えています。手元の環境で使えるかどうかは、実際にバインディングを設定して表示を確認するのが確実です。
カスタムフィールドの値を段落に表示する
core/post-meta で投稿メタを表示する手順は2つです。メタキーを登録することと、ブロックにバインディングを設定することです。
1. register_post_meta でメタキーを登録する
ブロックバインディングから読めるのは、register_post_meta() で登録済みのメタキーだけです。show_in_rest を true にして、REST API から見える状態にしておく必要があります。
function mytheme_register_book_meta() {
register_post_meta(
'post', // 対象の投稿タイプ
'book_author', // メタキー(先頭にアンダースコアを付けない)
array(
'show_in_rest' => true, // 必須。エディターから読めるようにする
'single' => true, // 値をひとつだけ持つ
'type' => 'string',
'label' => __( '著者名', 'mytheme' ), // 設定 UI に表示される名前
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
)
);
}
add_action( 'init', 'mytheme_register_book_meta' );
ここで大事なのがメタキーの先頭にアンダースコアを付けないことです。_book_author のように書くと WordPress では「保護されたメタ(protected meta)」として扱われ、REST API 経由で読み書きできなくなるため、バインディングからも参照できません。
label は WordPress 6.7 以降でエディターの設定 UI に表示される項目名です。指定しておくと、後述の「属性」パネルでメタキーの生の文字列ではなく日本語のラベルが並ぶので、投稿を書く人が選びやすくなります。
2. ブロックにバインディングを設定する
バインディングの情報は、ブロックの metadata.bindings という属性に保存されます。コードエディター(投稿画面の「コードエディター」表示)で見ると、次のような形になっています。
<!-- wp:paragraph {
"metadata":{
"bindings":{
"content":{
"source":"core/post-meta",
"args":{"key":"book_author"}
}
}
}
} -->
<p>ここに入力した文字は表示されません</p>
<!-- /wp:paragraph -->
bindings のキー(ここでは content)がバインドする属性名、source がデータソース名、args がソースに渡す引数です。core/post-meta は key という引数でメタキーを受け取ります。
本文に書いた「ここに入力した文字は表示されません」は、バインディングが有効なあいだフロントエンドには出ません。メタの値が空だったときのフォールバックとして残る場合もありますが、表示される文字列はメタの値が優先されると考えてください。
WordPress 6.6 以降は、段落ブロックを選択したときに右サイドバーの「高度な設定」に「属性」パネルが表示され、そこからマウス操作でメタキーを選べます。手で JSON を書かずに設定できるので、実際の運用ではこちらを使うことがほとんどでしょう。さらに 6.6 以降では、バインドされた段落をエディター上で直接編集すると投稿メタ側が更新される(読み取り専用ではなく双方向になる)動作もサポートされています。
自作のデータソースを登録する
投稿メタ以外の値——たとえば外部 API の結果、オプション値、計算した文字列——を差し込みたいときは、register_block_bindings_source() で独自のソースを登録します。
function mytheme_register_binding_sources() {
register_block_bindings_source(
'mytheme/copyright', // ソース名。必ず「名前空間/名前」の形にする
array(
'label' => __( 'コピーライト', 'mytheme' ),
'get_value_callback' => 'mytheme_copyright_binding',
'uses_context' => array( 'postId' ), // コールバックで使いたいコンテキスト
)
);
}
add_action( 'init', 'mytheme_register_binding_sources' );
/**
* 実際に表示する値を返すコールバック。
*
* @param array $source_args ブロック側の args。
* @param WP_Block $block_instance ブロックのインスタンス。
* @param string $attribute_name バインド先の属性名(content など)。
* @return string 表示する値。
*/
function mytheme_copyright_binding( $source_args, $block_instance, $attribute_name ) {
$owner = isset( $source_args['owner'] ) ? $source_args['owner'] : get_bloginfo( 'name' );
return sprintf( '© %s %s', gmdate( 'Y' ), $owner );
}
register_block_bindings_source() に渡す設定は次の3つです。
| 項目 | 説明 |
|---|---|
label | エディターの UI に表示される、人間が読むための名前 |
get_value_callback | 実際の値を返す関数。返り値がブロックの属性に差し込まれる |
uses_context | コールバックで参照したいブロックコンテキストのキーの配列(省略可) |
登録は必ず init フックの中で行います。ソース名は core/ 以外の名前空間を付ける決まりで、テーマ名やプラグイン名を使うのが一般的です。
作ったソースをブロックから使うときは、source にそのソース名を書きます。args に入れた値がそのままコールバックの第1引数に渡ります。
<!-- wp:paragraph {
"metadata":{
"bindings":{
"content":{
"source":"mytheme/copyright",
"args":{"owner":"webool"}
}
}
}
} -->
<p>コピーライト</p>
<!-- /wp:paragraph -->
これで、フロントエンドでは「© 2026 webool」と表示されます。args の設計を工夫すれば、ひとつのソースでいろいろな値を返せるので、用途ごとにソースを乱立させずに済みます。
コールバックの第3引数で属性ごとに値を変える
コールバックの第3引数 $attribute_name には、バインド先の属性名が入ります。画像ブロックのように url と alt の両方をバインドしたいときは、この値で分岐させます。
function mytheme_author_photo_binding( $source_args, $block_instance, $attribute_name ) {
$post_id = $block_instance->context['postId'];
$author_id = get_post_field( 'post_author', $post_id );
// バインド先の属性ごとに返す値を変える
if ( 'alt' === $attribute_name ) {
return get_the_author_meta( 'display_name', $author_id ) . 'のプロフィール写真';
}
return get_avatar_url( $author_id, array( 'size' => 200 ) );
}
$block_instance->context から値を取り出せるのは、登録時に uses_context でそのキーを宣言している場合だけです。上の例のように postId を使うなら、'uses_context' => array( 'postId' ) の指定を忘れないようにしてください。
値が表示されないときに確認すること
バインディングを設定したのに、フロントで空になったり、エディターに書いた文字がそのまま出たりすることがあります。原因はだいたい決まっています。
メタキーが登録されていない・保護されている
core/post-meta でいちばん多いのがこれです。カスタムフィールド用のプラグインで値を入れているだけでは register_post_meta() の登録にはならないことがあり、その場合バインディングからは見えません。show_in_rest が true になっているか、メタキーの先頭にアンダースコアが付いていないかを確認します。
また、register_post_meta() の第1引数の投稿タイプが、実際に使っている投稿タイプと一致している必要があります。固定ページで使うなら 'page'、カスタム投稿タイプならそのスラッグを指定します。
ソースの登録が init より後になっている
register_block_bindings_source() を init 以外の遅いフック(wp や template_redirect など)で呼ぶと、レンダリング時にソースが見つからず、バインディングが無視されます。register_post_meta() も同様に init で登録するのが原則です。
コールバックが文字列以外を返している
get_value_callback の返り値はそのまま属性の値になります。配列やオブジェクトを返すと期待どおりに表示されません。数値を返す場合も、最終的に文字列として出力される点を意識して、フォーマット済みの文字列を返すようにしておくと安全です。値が存在しないケースでは空文字を返すようにし、null や false を返さないほうがトラブルが少なくなります。
ブロックが対応していない属性を指定している
先ほどの表にない属性——たとえば段落ブロックの align や、リストブロックの values ——をバインドしようとしても効きません。エラーも出ずに単に無視されるので、動かないときは「そのブロックのその属性がバインディング対応か」を疑ってみてください。
まとめ
ブロックバインディングは、既存のブロックの属性に外部の値を紐づける仕組みです。カスタムフィールドを表示したいだけならブロックを自作する必要はなく、register_post_meta() で show_in_rest => true のメタを登録し、段落ブロックの「属性」パネルからそのメタを選ぶだけで実現できます。
投稿メタ以外の値を扱いたいときは、init フックで register_block_bindings_source() を呼び、get_value_callback で表示したい文字列を返します。uses_context に postId などを宣言しておけば、コールバックの中で投稿ごとの情報も参照できます。ブロックを一から作るより手数が少なく、見た目の調整はコアブロックの機能に任せられるのが大きな利点です。