WordPress Logo WordPress Block Bindings API の基本的な使い方

WordPress 6.5 で追加された Block Bindings API は Gutenberg ブロックの属性値にカスタムフィールドやカスタムソースなどの動的なデータ(外部データソース)を接続(バインド) する仕組みです。

以下では、実用的なサンプルコードはありませんが、ブロックバインディングの基本的な構造と使い方を整理して解説します。また、ブロックバリエーションを使った例も掲載しています。

この記事の執筆時点の WordPress のバージョンは 6.8.2 です。

更新日:2025年09月08日

作成日:2025年09月07日

ブロックとバインディングの基本構造

Block Bindings API は、ブロックの 属性(attribute) に動的なデータを「バインド」し、その値を最終的な HTML マークアップに反映させる仕組みです。

例えば、投稿のカスタムフィールドやサイトの設定値などを使って、画像ブロックの url 属性にカスタム URL を挿入したり、alt 属性に動的なテキストを挿入したりできます。

画像ブロックの例

ブロックエディターで画像を挿入する際に使用する画像ブロックの HTML マークアップ(ブロックマークアップ)は次のようになっています。

<!-- wp:image -->
<figure class="wp-block-image"><img src="" alt=""/></figure>
<!-- /wp:image -->

このとき、img 要素の src 属性や alt 属性に対応するブロック属性(url, alt)が内部的に管理されており、次のように対応しています。

  • url 属性 → <img src="...">(img 要素の src 属性)
  • alt 属性 → <img alt="...">(img 要素の alt 属性)

属性の定義(block.json の attributes)

各ブロックがどのような属性(attributes プロパティ)を持つかは、各ブロックの block.json ファイルで定義されています。以下は画像ブロックの block.json の url 属性と alt 属性の抜粋です。

{
  "attributes": {
    "url": {
      "type": "string",
      "source": "attribute",
      "selector": "img",
      "attribute": "src",
      "role": "content"
    },
    "alt": {
      "type": "string",
      "source": "attribute",
      "selector": "img",
      "attribute": "alt",
      "default": "",
      "role": "content"
    }
  }
}

ここで定義されている内容(ブロック属性)は「保存された HTML から属性値をどのように抽出・復元するか」を表しています。

  • url → <img src="..."> から値を取り出す
  • alt → <img alt="..."> から値を取り出す

ポイント

  • ブロック属性とは、block.json の attributes プロパティで定義され、ブロックエディター内部で管理されるデータ
  • ブロック属性は HTML のどの部分と対応しているかが明確に決まっている
  • Block Bindings API は、その属性に外部データをバインドする仕組み

ブロックエディターで画像を挿入した実際の画像ブロックのマークアップは、次のようにブロックの設定を表す JSON コードや各 HTML 属性及びその値が含まれます。

<!-- wp:image {
  "lightbox":{"enabled":true},
  "id":1,
  "sizeSlug":"large",
  "linkDestination":"none"
} -->
<figure class="wp-block-image size-large">
  <img src="/path/to/image.jpg" alt="This is the image alt text" class="wp-image-1"/>
</figure>
<!-- /wp:image -->

上記のマークアップはブロック属性に関して次のことを示しています。

  • url 属性は img 要素の src 属性の "/path/to/image.jpg"
  • alt 属性は img 要素の alt 属性の "This is the image alt text"

Block Bindings API は、これらのブロック属性に外部データを直接接続できる仕組みです。

どのデータをバインドできるかは block.json で定義された属性に依存します。そのため、属性と HTML の対応関係を理解しておくことが重要になります。

これまでは、WordPress のブロックエディターでカスタムデータを表示するには、カスタムブロックを作成してカスタムフィールドやその他のソースからデータを取得する必要がありましたが、Block Bindings API を使用すると、簡単にデータソースを WordPress のコアブロックに関連付けることができます。

以下は、架空のバインディングソースからデータを取得して表示する画像ブロックの例です。

<!-- wp:image {
  "metadata":{
    "bindings":{
      "url":{
        "source":"namespace/slug",
        "args":{
          "key":"some-field"
        }
      },
      "alt":{
        "source":"namespace/slug",
        "args":{
          "key":"some-other-field"
        }
      }
    }
  }
} -->
<figure class="wp-block-image">
<img src="" alt="" />
</figure>
<!-- /wp:image -->

このマークアップでは、画像ブロック(wp:image)の url 属性(画像のパス)や alt 属性(代替テキスト)が、Block Bindings API で登録したデータソースにひも付けられています。

それぞれのプロパティの意味は以下のとおりです。

  • metadata: ブロックに追加情報を付与するためのオブジェクト。
  • bindings: 実際に「どの属性を、どのデータソースにひも付けるか」を定義する場所(オブジェクト)。
  • url / alt: 画像ブロックの属性。ここで指定した属性に、データソースから取得した値が反映されます。
  • source: どのデータソースを使うか(Block Bindings API で登録した名前)。
  • args: データソースに渡す追加パラメータ。この例では key にフィールド名を指定しています。

Block Bindings API によって、様々なソースからの動的なデータをブロック属性に関連付けることができるようになります。但し、現時点でサポートされているのは一部のコアブロックと属性に限られています。

執筆時点(WordPress 6.8)で利用できるブロックと属性

サポートされているブロック サポートされている属性(attributes)
段落ブロック(Paragraph content
見出しブロック(Heading content
画像ブロック(Image id, url, title, alt
ボタンブロック(Button text, url, linkTarget, rel

カスタムフィールドをブロック属性に接続

Block Bindings API の主なユースケースの一つは、カスタムフィールド(投稿メタデータ)をブロックに接続(バインド)することです。

例えば、段落ブロックにカスタムフィールドの値を自動表示したり、画像ブロックにカスタムフィールドから取得した画像 URL と代替テキストを反映させることができます。

ブロックエディターでカスタムフィールドを有効にする

この例では、カスタムフィールドの編集はカスタムフィールドパネルを利用します(WordPress 6.6 以降では、カスタムフィールドパネルを介さずにブロックから直接編集できるようになっています)。

ブロックエディターの右上のオプションメニュー()から「設定」を開き、「パネル」→「高度な設定」で「カスタムフィールド」をオンにします。その後「ページを表示して、リロード」というボタンが表示されるので、クリックして反映します。

【参考】ACF(Advanced Custom Fields)プラグインを利用している場合、このトグルは表示されません。代わりに、ACF で定義したカスタムフィールドが自動的にメタボックスとして表示されます。

カスタムフィールドを有効にすると(編集画面のリロードを実行すると)、以下のように投稿編集画面下部にカスタムフィールドの欄が追加されます。

テキストを段落ブロックにバインド

以下はカスタムフィールドに使用するメタキーを登録し、それを段落ブロックにバインドする最もシンプルな例です。

カスタムフィールドを登録

カスタムフィールドをブロックにバインドするには、まずメタキーを登録する必要があります。

テーマの functions.php に以下を記述して、カスタムフィールドに使用するメタキーを登録します。

メタキーを登録するには、register_meta()register_post_meta() 関数を使用します。

add_action('init', 'wdl_register_meta');
// register_meta()を使ってカスタムフィールドを登録
function wdl_register_meta() {
  register_meta(
    'post',  // メタデータを関連付けるオブジェクトの種類
    'wdl_message',  // 登録するメタキー(カスタムフィールド名)
    array(
      'show_in_rest'      => true, // REST API でこのフィールドを公開
      'single'            => true, // 単一の値
      'type'              => 'string',  // テキストフィールド
      'sanitize_callback' => 'wp_strip_all_tags'  // 入力をサニタイズ
    )
  );
}

ここで 'show_in_rest' => true を指定することで、REST API およびブロックエディターから利用できるようになります。

サニタイズ関数には wp_strip_all_tags を指定して HTML を除去していますが、用途によっては独自のサニタイズ関数を用意することもできます。

カスタムメタ情報の登録に関する詳細は以下のドキュメントを参照してください。

Advanced Custom Field プラグインを使用する場合も、同様にカスタムメタ情報の登録が必要です。また、フィールドグループの設定で「REST API で公開」を有効にします。

カスタムフィールドの値をページに追加

WordPress 管理画面から投稿エディターを開き、「カスタムフィールド」パネルまでスクロールし、「名前」フィールドに「wdl_message」キーを追加し、「値」フィールドに任意のテキストを入力します。

そして「カスタムフィールドを追加」ボタンをクリックします。

ブロックマークアップを追加

執筆時点の WordPress バージョンでは、カスタムフィールドをバインドするための専用 UI はまだありません。そのため、コードエディターを使ってマークアップを追加する必要があります(バインディングを設定できる UI が今後追加される可能性もあります)。

コードエディタービューは、画面右上にあるオプションメニュー()からアクセスできます。

例えば、新規に投稿を作成して、まだ何もブロックを挿入していない状態だと以下のように表示されます。

「テキストまたは HTML を入力して開始」の部分にマークアップを追加します。

上記スクリーンショットのように次のブロックマークアップをエディターに追加します。

<!-- wp:paragraph {
  "metadata":{
    "bindings":{
      "content":{
        "source":"core/post-meta",
        "args":{
          "key":"wdl_message"
        }
      }
    }
  }
} -->
<p></p>
<!-- /wp:paragraph -->

カスタムフィールドを段落ブロックにバインドするにはコードエディターから直接マークアップを追加します(現状はコードエディターを使う必要がありますが、今後のバージョンでは専用 UI が期待されます)。

このとき、段落の本文にあたる content 属性を、core/post-meta ソース経由で wdl_message メタキーに接続しています。

以下は、入力したブロックマークアップのネストされたプロパティの概要です。

プロパティ 説明
metadata ブロックに関するメタデータを含むオブジェクト。
bindings ブロックのバインディングを1つ以上含むオブジェクト。
content カスタムフィールドにバインドするブロック属性。この例の場合は、Paragraph ブロックの content 属性(段落のテキスト本文にあたる部分)。
source Block Bindings API 経由で登録されたバインディングソース(サーバー側で戻り値を処理します)。カスタムフィールドを使用するには、core/post-meta に設定します。
args ブロックバインディングソースに渡す1つ以上の引数を含むオブジェクト。カスタムフィールドの場合は、常に key プロパティに、ブロック属性にバインドするメタキーの名前を設定します。

コードエディターを終了して、ビジュアルエディタービューに戻ると、最初は、wdl_message キーが段落コンテンツとして表示されます。

投稿を保存すると、カスタムフィールドパネルに入力した値が段落コンテンツとして表示されます(保存後、再読み込みが必要になる場合があります)。

この例の場合、カスタムフィールドパネルを有効にして(表示して)いるので、表示される段落コンテンツは編集できないようになっています。

ブロック設定に「属性」セクションが表示されます。このセクションには、ブロックバインディングで使用できるカスタムフィールドの一覧が表示されます。

サイトのフロントエンドで投稿を表示すると、全く同じ出力が表示されます。

実際の利用

実際の利用では、毎回コード(ブロックマークアップ)を記述するのではなく、ブロックバリエーションブロックパターンテーマテンプレートに組み込んでおくのが実用的です。

ブロックからカスタムフィールドを編集

WordPress 6.6 以降では、投稿メタに接続されたブロック属性を、カスタムフィールドパネルを介さずにブロックから直接編集できるようになりました。

これは、ブロックが core/post-meta ソースにバインドされている場合に有効で、編集内容は即座にカスタムフィールドに反映されます。

なお、この機能を使うには「カスタムフィールド」パネルを無効にしておく必要があります。これは、同じ値をブロックとパネルの両方から編集して矛盾が起きるのを避けるための仕様と思われます。

カスタムフィールドパネルを有効にして表示している場合は、「設定」を開き、「一般」タブで「高度な設定」の「カスタムフィールド」のトグルをオフにして、「ページを隠して、リロード」をクリックします。

ブロック属性が投稿メタソースに接続されている場合、編集時に自動的にカスタムフィールドの値に接続されます。

また、WordPress 6.6 では以下のような機能も追加されています。

  • クエリループからカスタムフィールドを更新可能に。
  • 複数のブロックが同じカスタムフィールドに接続されている場合、それらの値が同期されます。
  • ユーザーは、権限のある投稿からのみカスタムフィールドを編集できます。

詳細は以下で確認できます。

Editing custom fields from connected blocks

Advanced Custom Fields の注意点

プラグイン Advanced Custom Fields(ACF) で作成したカスタムフィールドをブロックにバインドする場合には注意が必要です。現時点では、ブロック側からカスタムフィールドの値を直接編集しても、保存時に実際のカスタムフィールド値には反映されません。カスタムフィールドの更新は、ACF のメタボックスから行う必要があります(今後の ACF の対応状況次第で変わる可能性があります)。

画像ブロックでの複数のバインディング

1つのブロックに2つの異なるバインディングを登録する例です。画像ブロックにカスタム URL と代替テキストを追加します。手順はほぼ同じです。

また、この例では、カスタムフィールドパネルを有効にして、カスタムフィールド入力欄を表示してある状態になっています。

投稿のメタデータキーを登録

まず、投稿のメタデータキー(カスタムフィールド)を2つ登録します。

  • wdl_image_url: 画像ブロックの url 属性にバインドする URL
  • wdl_image_alt: alt 属性にバインドする代替テキスト

テーマの functions.php を開き、先ほど追加した wdl_register_meta() 関数内に以下を追加します。

register_meta(
  'post',  // メタデータを関連付けるオブジェクトの種類
  'wdl_image_url',  // 登録するメタキー(カスタムフィールド名)
  array(
    'show_in_rest'      => true, // REST API でこのフィールドを公開
    'single'            => true, // 単一の値
    'type'              => 'string', // テキストフィールド
    'sanitize_callback' => 'esc_url_raw' // 入力を URL としてサニタイズ
  )
);

register_meta(
  'post',
  'wdl_image_alt',  // 登録するメタキー(カスタムフィールド名)
  array(
    'show_in_rest'      => true, // REST API でこのフィールドを公開
    'single'            => true, // 単一の値
    'type'              => 'string', // テキストフィールド
    'sanitize_callback' => 'wp_strip_all_tags'  // 入力をサニタイズ
  )
);
add_action('init', 'wdl_register_meta');
function wdl_register_meta() {
  register_meta(
    'post',
    'wdl_message',
    array(
      'show_in_rest'      => true,
      'single'            => true,
      'type'              => 'string',
      'sanitize_callback' => 'wp_strip_all_tags'
    )
  );

  register_meta(
    'post',  // メタデータを関連付けるオブジェクトの種類
    'wdl_image_url',  // 登録するメタキー(カスタムフィールド名)
    array(
      'show_in_rest'      => true, // REST API でこのフィールドを公開
      'single'            => true, // 単一の値
      'type'              => 'string', // テキストフィールド
      'sanitize_callback' => 'esc_url_raw' // 入力を URL としてサニタイズ
    )
  );

  register_meta(
    'post',
    'wdl_image_alt',  // 登録するメタキー(カスタムフィールド名)
    array(
      'show_in_rest'      => true, // REST API でこのフィールドを公開
      'single'            => true, // 単一の値
      'type'              => 'string', // テキストフィールド
      'sanitize_callback' => 'wp_strip_all_tags'  // 入力をサニタイズ
    )
  );
}

ブロックマークアップをエディターに追加

管理画面の投稿エディターで、コードエディタービューを開き、次のブロックマークアップを追加します。

<!-- wp:image {
  "metadata":{
    "bindings":{
      "url":{
        "source":"core/post-meta",
        "args":{
          "key":"wdl_image_url"
        }
      },
      "alt":{
        "source":"core/post-meta",
        "args":{
          "key":"wdl_image_alt"
        }
      }
    }
  }
} -->
<figure class="wp-block-image">
<img src="" alt="" />
</figure>
<!-- /wp:image -->

ブロックの bindings プロパティには複数の属性を含めることができます。

前述の段落ブロックの場合は、bindings プロパティにブロックのバインディングとして Paragraph ブロックの content 属性を指定しましたが、この例の画像ブロックでは、Image ブロックurl 属性と alt 属性を指定します。

カスタムフィールドを使用するので、それぞれの属性の source プロパティ(バインディングソース)には core/post-meta を指定し、args プロパティ(バインディングソースに渡すオブジェクト)には key プロパティにブロック属性にバインドするメタキー(カスタムフィールド)の名前を設定します。

コードを追加したら、コードエディタービューを終了してビジュアルエディターに戻ると、画像ブロックのプレースホルダーが表示されます。

画像ブロックを選択すると以下のように表示されます(カスタムフィールド入力欄が表示されている場合)。

画像ブロックの UI には、ブロックがカスタムフィールドに接続されていることを示すメッセージ「投稿メタへの接続」と表示されます。

ブロックのサイドバーパネルを見ると、代替テキストフィールドにも同じメッセージが表示され、「属性」セクションが表示されます。

また、この例の場合、カスタムフィールド入力欄が表示されているので、画像のアップロード( url 属性)と代替テキストフィールド(alt 属性)の両方が編集できないようにロックされています。

次に、投稿エディターのカスタムフィールドパネルで、wdl_image_url メタキーにカスタム画像 URL を入力し、wdl_image_alt にカスタムテキストを入力します。

投稿を保存して再読込すると、画像ブロックが正しい画像と代替テキストとともに UI に表示されます。

フォールバックメタ値の追加(default)

register_meta() 関数では、デフォルトフィールドを登録することができます。メタキーを登録する際にこのフィールドを設定すると、ユーザーがメタ値(カスタムフィールド)を設定するまで、このフィールドがデフォルト値として表示されます。

以下の例では、前述の画像ブロックのメタキーを登録したコードで、wdl_image_url メタキーに新しいデフォルト引数 'default' を追加し、テーマフォルダ内の画像 URL(assets/images/default.jpg)を設定しています。

register_meta(
  'post',
  'wdl_image_url',
  array(
    'show_in_rest'      => true,
    'single'            => true,
    'type'              => 'string',
    'sanitize_callback' => 'esc_url_raw',
    // デフォルト値(フォールバックメタ値)を設定
    'default'           => get_theme_file_uri( 'assets/images/default.jpg' )
  )
);

この default 値は、ユーザーがカスタムフィールドをまだ入力していない場合にのみ使用されます。一度値を保存すると、その値が優先され、default は使われません。

これはダミー画像やプレースホルダーなど、ユーザーがカスタム値を入力していない場合にデフォルトの値を出力したい場合に便利です。

ユーザーがまだカスタムフィールドを入力していない状態では、例えば、次のように default に指定した画像が表示されます。

ブロックからカスタムフィールドを編集

先述の段落ブロック同様、接続されたブロックからカスタムフィールドの値を直接編集できます。

この例では、カスタムフィールドパネルを有効にしているので、「設定」で「カスタムフィールド」のトグルをオフにしてカスタムフィールドパネルを無効にして非表示にしておきます。

画像ブロックを選択すると、「置換ボタン」が表示され、画像( url 属性)を変更することができ、また、サイドバーの代替テキストフィールド(alt 属性)も編集できるようになります。

上記の例は、すでにカスタムフィールドの値を設定してある状態ですが、まだカスタムフィールドの値を設定していない場合は、例えば以下のように表示され、画像や代替テキストを設定できます。

参考ページ

カスタムバインディングソース

ブロックバインディングに使用できるのは、カスタムフィールドの値だけではありません。

Block Bindings API には、カスタムソースの登録も可能にする機能が備わっていて、これはカスタムフィールド(core/post-meta)を登録するために内部的に使用される機能と同じです。

カスタムソースを登録するには Block Bindings API の PHP 関数 register_block_bindings_source() を使用します。カスタムソースの登録は、init フックで行います。

register_block_bindings_source()

以下は register_block_bindings_source() の書式です。

register_block_bindings_source(
  string $source_name,
  array $source_properties
);
パラメータ 説明
$source_name 「名前空間/スラッグ」形式のカスタムバインディングソースの一意の名前。
$source_properties

バインディングソースを定義するプロパティの配列

  • label: バインディングソースを表すテキスト文字列(ラベル)。
  • get_value_callback: ブロックの属性が $source_name パラメータに一致した場合に呼び出される PHP 関数(呼び出し可能オブジェクト)。以下参照。
  • uses_context: (オプション) コールバックに必要な場合、ブロックインスタンスをコンテキストの配列で拡張します。例えば、現在の投稿 ID が必要な場合は、['postId'] に設定します。
get_value_callback

WordPress はブロックを解析中にカスタムバインディングソースに遭遇すると、第2パラメータに指定した get_value_callback 関数を実行します。この関数の書式は次のようになります。

projectslug_bindings_callback(
  array $source_args,
  WP_Block $block_instance,
  string $attribute_name
);

以下の3つのパラメータを指定できますが、必要ない場合はそれぞれ定義する必要はありません。

パラメータ 説明
$source_args ブロックから metadata.bindings.$attribute.args プロパティを介して渡される引数の配列。
$block_instance バインディングが接続されているブロックの現在のインスタンス(WP_Block オブジェクト)。WP_Block クラスは wp=includes/class-wp-block.php で定義されています。
$attribute_name ブロックの metadata.bindings.$attribute プロパティを介して設定されている現在の属性。

get_value_callback 関数は、ブロックの属性に設定する値を返すためのコールバックです。WordPress がブロックを描画するときに呼び出され、戻り値がそのまま対象属性の値として反映されます。

  • コールバック関数はブロックごとに呼び出される
  • 第3引数 $attribute_name によって「どの属性に値を設定しようとしているか」が分かる
  • 関数は その属性に設定する値(文字列・数値・配列など) を返す
  • 返された値は、実際のブロックの 属性値(attributes の該当キー) として反映される

以下は「現在の日付を返すカスタムソース」を登録する例です。

このソースには get_value_callback が指定されており、ここで返す値(date_i18n( get_option( 'date_format' ) ) = 現在の日付)が ブロックの属性に設定される値になります。

add_action( 'init', function() {
  register_block_bindings_source(
    'wdl/current-date',
    array(
      'label' => __( '今日の日付', 'text-domain' ),
      'get_value_callback' => function() {
        return date_i18n( get_option( 'date_format' ) );
      },
    )
  );
} );

ブロックマークアップ内で以下のように指定すると、段落ブロックの content 属性に対してカスタムソース(wdl/current-date)が紐付けられ、実際のレンダリング時には get_value_callback の戻り値(「今日の日付」ではなく その時点の現在日付)が content 属性に反映されます。

<!-- wp:paragraph
  {"metadata":{
    "bindings":{
      "content":{
        "source":"wdl/current-date"
      }
    }
  }
 } -->
<p>今日の日付</p>
<!-- /wp:paragraph -->

カスタムソース登録例

複数の属性にバインド

以下は画像ブロックにカスタム画像をバインドする例です。テーマフォルダ内の assets/images/ に配置してある画像を表示します。

コールバック関数では、引数の $attribute_name を使って属性を判定しています。

add_action('init', function () {
  register_block_bindings_source(
    'wdl/custom-image',
    array(
      'label' => __('Custom image source', 'text-domain'),
      'get_value_callback' => 'wdl_custom_image_binding'
    )
  );
});


function wdl_custom_image_binding($source_args, $block_instance, $attribute_name) {
  // url 属性
  if ('url' === $attribute_name) {
    if (! empty($source_args['filename'])) {
      return get_theme_file_uri("assets/images/{$source_args['filename']}");
    } else {
      // url 属性が空の場合はデフォルトの画像を表示
      return get_theme_file_uri('assets/images/default.jpg');
    }
  }

  // alt 属性
  if ('alt' === $attribute_name) {
    if (! empty($source_args['alt_text'])) {
      return  $source_args['alt_text'];
    } else {
      // url 属性が空の場合はデフォルトの画像を表示
      return 'Some custom alternative text.';
    }
  }
}

この例では、1つのカスタムソース wdl/custom-image を使って、画像ブロックの url 属性と alt 属性の両方にバインドしています。

コールバック関数 wdl_custom_image_binding() には、以下の3つの引数が渡されます。

  • $source_args:ブロックマークアップの args プロパティで指定された値を受け取る配列。
    • (例)url 属性の場合 → {"filename":"sample.jpg"}
    • (例)alt 属性の場合 → {"alt_text":"Alternative text for sample image"}
  • $block_instance:現在処理中のブロックインスタンス。今回は使っていません。
  • $attribute_name:現在どの属性を処理しているかを表す文字列。
    • url 属性を処理中なら 'url'
    • alt 属性を処理中なら 'alt';

動作の流れ

  1. もし $attribute_nameurl なら、$source_args['filename'] を使ってテーマフォルダ内の画像 URL を組み立てます。値がなければデフォルト画像を返します。
  2. もし $attribute_namealt なら、$source_args['alt_text'] を代替テキストとして返します。値がなければデフォルトのテキストを返します。

以下はブロックマークアップの例です。

<!-- wp:image {
  "metadata":{
    "bindings":{
      "url":{
        "source":"wdl/custom-image",
        "args":{
          "filename":"sample.jpg"
        }
      },
      "alt":{
        "source":"wdl/custom-image",
        "args":{
          "alt_text":"Alternative text for sample image"
        }
      }
    }
  }
} -->
<figure class="wp-block-image"><img alt=""/></figure>
<!-- /wp:image -->
uses_context コンテキストを受け取る

以下は、投稿のカテゴリーごとに異なる画像を表示する仕組みの例です。テーマフォルダの assets/images/ に、カテゴリーのスラッグ名と同じ名前の画像ファイル(例:スラッグが news なら news.jpg)を配置しておくと、その画像が表示されます。該当するファイルが存在しない場合は default.jpg が表示されます。

この例では、uses_context に ['postId'] を指定して、コールバック関数で現在編集中の投稿 ID を受け取れるようにしています。

  • register_block_bindings_source() の uses_context プロパティを設定すると、コールバック関数で $block_instance->context に投稿 ID などの情報が渡されます(context は連想配列)。
  • ここでは get_the_category() を使って 投稿のカテゴリー情報 を取得し、そのスラッグに対応する画像をテーマフォルダ内から読み込んでいます(テーマフォルダ内の assets/images/ にカテゴリーのスラッグ名の画像を配置しておきます)。
add_action('init', function () {

  register_block_bindings_source(
    'wdl/category-image',
    array(
      'label' => __('Category image source', 'text-domain'),
      'get_value_callback' => 'wdl_category_image_binding',
      'uses_context'       => ['postId'] // 現在の投稿 ID
    )
  );
});

function wdl_category_image_binding($source_args, $block_instance, $attribute_name) {

  // 現在の投稿 ID からカテゴリー(配列)を取得
  $categories = get_the_category($block_instance->context['postId']);
  // カテゴリー未設定の投稿だと空配列になるので、念の為 !empty() でチェックして最初の要素を取得
  $cat = ! empty($categories) ? $categories[0] : null;

  if ('url' === $attribute_name) {
    // カテゴリーのスラッグを取得
    $cat_slug = $cat->slug;
    // カテゴリーのスラッグ名の画像($cat_slug.jpg)のパスを取得
    $cat_image_path = get_theme_file_path("assets/images/{$cat_slug}.jpg");
    // カテゴリー用画像が存在すれば
    if (file_exists($cat_image_path)) {
      // カテゴリー用画像の URL を返す
      return get_theme_file_uri("assets/images/{$cat_slug}.jpg");
    } else {
      // カテゴリー用画像が存在しない場合はデフォルト画像の URL を返す
      return get_theme_file_uri('assets/images/default.jpg');
    }
  }

  if ('alt' === $attribute_name) {
    if (! empty($source_args['alt_text'])) {
      return  $source_args['alt_text'];
    } else {
      return 'An image for ' . $cat->name . ' category';
    }
  }
}

uses_context

register_block_bindings_source() でカスタムソースを登録する際に、uses_context を指定すると、その値がコールバック関数の第2引数 $block_instance に含まれます。

  • 第2引数 $block_instance
    • WP_Block オブジェクトが渡される。
    • その中に context プロパティ(連想配列)があり、uses_context で列挙した値が格納される。
    • この例では ['postId'] を指定したため、$block_instance->context['postId'] で現在の投稿 ID を取得できる。

コールバックの動作

  • url 属性の場合
    • 投稿のカテゴリーのスラッグに対応する画像ファイル(例: category-slug.jpg)があればその URL を返し、なければデフォルト画像を返します。
  • alt 属性の場合
    • args に alt_text が指定されていればその値を返し、指定されていなければ「カテゴリー名を含んだ代替テキスト」を返します。

以下はブロックマークアップの例です。

<!-- wp:image {
  "metadata":{
    "bindings":{
      "url":{
        "source":"wdl/category-image"
      },
      "alt":{
        "source":"wdl/category-image",
        "args":{
          "alt_text":"Alternative text for category image"
        }
      }
    }
  }
} -->
<figure class="wp-block-image"><img alt=""/></figure>
<!-- /wp:image -->

uses_context の仕組み

uses_context は、ブロックが親ブロックなどから コンテキスト情報を受け取るための仕組み です。

ブロックの block.json に usesContext を定義すると、そのブロックは指定したキー名のコンテキストを利用できるようになります。

{
  "name": "my-plugin/child-block",
  "usesContext": [ "postId", "postType" ]
}

この例では、postId と postType というコンテキストを受け取ることができます。

WordPress コアブロックの多く(例:core/post-titlecore/post-content など)も、この仕組みを利用して現在の投稿情報を自動的に取得しています。

  • どの context が利用できるかはブロックごとに異なります。
  • WordPress のコアブロックが提供している context は、各ブロックの block.json ファイルの usesContext に定義されているので確認できます。

参考ページ

ブロックバリエーションの利用

ブロックバリエーションを登録しておくと、ブロック挿入時の選択肢として表示され、ユーザーはコードエディターを開かずに「バインド済みのブロック」を簡単に挿入できるようになります。

ブロックバリエーションの登録は、PHP(get_block_type_variations フック)を使う方法と JavaScript(registerBlockVariation() 関数)を使う方法があります。

ブロックバリエーションの詳細については以下を御覧ください。

get_block_type_variations フックで登録

以下はカスタムフィールドをバインドした段落ブロックをブロックバリエーションとして登録する例です。

カスタムフィールドに使用するメタキーを register_post_meta() や register_meta() 関数を使って登録しておきます。

add_action('init', function () {

  register_post_meta(
    'post',  // メタデータを関連付けるオブジェクトの種類
    'wdl-book-genre',  // 登録するメタキー(カスタムフィールド名)
    array(
      'show_in_rest'      => true, // REST API でこのフィールドを公開
      'single'            => true, // 単一の値
      'type'              => 'string',  // テキストフィールド
      'sanitize_callback' => 'wp_strip_all_tags', // 入力をサニタイズ
      'default'      => 'Default text for book genre',  // デフォルト値
    )
  );
});

ブロックバリエーションを登録

この例では、get_block_type_variations フック(PHP)を使って、段落ブロック(core/paragraph)に「Book Genre」というカスタムバリエーションを追加しています。

add_filter('get_block_type_variations', function ($variations, $block_type) {

  // バリエーションを登録するブロックかどうかをチェック(paragraph の場合にのみバリエーションを追加。paragraph 以外では早期 return)
  if ('core/paragraph' !== $block_type->name) {
    return $variations;
  }

  // $variations[] にバリエーションを構成するオプションの連想配列を追加
  $variations[] = array(
    'name' => 'wdl-book-genre',
    'title' => __( 'Book Genre', 'text-domain' ),
    'description' => 'Displays the book genre using custom field',
    'keywords' => array('book', 'genre'),
    'isDefault' => false,
    'icon' => 'book-alt', // ダッシュアイコン
    'attributes' => array(
      'metadata' => array(
        // ブロックバインディング
        'bindings' => array(
          'content' => array(
            'source' => 'core/post-meta',
            'args' => array(
              'key' => 'wdl-book-genre'
            )
          ),
        ),
      ),
    ),
    // 元のブロックのインスタンスとバリエーションを区別するための情報
    'isActive'   => array(
      'metadata'
    ),
  );

  return $variations;
}, 10, 2);

get_block_type_variations フックを使うと、既存のコアブロックに対して追加のバリエーションを紐づけることができ、$variations[] に設定を追加することで登録されます。

このコードでは、以下のようなオプションを指定しています。

  • attributes
    • metadata.bindings を使ってブロックバインディングを定義しています。ここでは段落ブロックの content をカスタムフィールド(post-meta)と連動させています。
  • isActive
    • バリエーションの判定条件を指定します。ここでは metadata 属性が存在する場合に、このブロックインスタンスが「Book Genre」バリエーションであると判断します。
  • title / description / icon
    • バリエーションを挿入する際にエディター上で表示される情報を指定しています。

上記のバリエーションを登録すると、ブロック挿入時の選択肢として表示され、インサーターから簡単に「カスタムフィールドにバインド済みの段落ブロック」を挿入できます。

この例では、メタキーの登録で default(デフォルト値)を設定しているので、ブロックを挿入するとデフォルト値のテキスト(Default text for book genre)が表示されます。

コードエディタービューに切り替えると、カスタムフィールドを段落ブロックにバインドしたブロックマークアップが確認できます。

registerBlockVariation() 関数で登録

JavaScript(Variations API)の registerBlockVariation() 関数を使う場合、別途 JavaScript ファイルを作成して読み込む必要がありますが、isActive にコールバック関数を指定して柔軟な判定ができ、また、アイコンにカスタム SVG を割り当てることができます。

以下では、先述のカスタムソースをバインディングするブロックをバリエーションとして登録します。

カスタムソースの登録

functions.php に以下のカスタムソースの登録が記述してあることを前提にしています。

add_action('init', 'wdl_register_block_bindings');

function wdl_register_block_bindings() {
  register_block_bindings_source(
    'wdl/copyright',  // カスタムバインディングソースの一意の名前
    array(
      'label'              => __('Copyright', 'text-domain'),  // ラベル
      'get_value_callback' => 'wdl_copyright_binding'  // コールバック
    )
  );
}

// コールバックの定義
function wdl_copyright_binding($source_args) {
  // args に starting_year プロパティが設定されていれば
  if (! empty($source_args['starting_year'])) {
    return '&copy; ' . $source_args['starting_year'] . '-' . date('Y');
  } else {
    return '&copy; ' . date('Y');
  }
}
JavaScript の読み込み

ブロックのバリエーションを JavaScript で登録するには、まず JavaScript ファイルを作成します。

この例ではテーマに追加します。block-variations.js という名前の JavaScript ファイルを作成し、テーマの /assets/js/ フォルダーに配置します(ファイルやフォルダーは任意の名前を付けられます)。

作成したファイルをエディターに読み込むには、enqueue_block_editor_assets フックと wp_enqueue_script() 関数を使用します。以下を functions.php に記述します。

add_action('enqueue_block_editor_assets', function () {
  wp_enqueue_script(
    'wdl-block-variations',
    get_theme_file_uri('assets/js/block-variations.js'),
    // 依存するスクリプトのハンドル名の配列
    array(
      'wp-blocks', // バリエーション登録に必要
      'wp-dom-ready', // エディター初期化後に実行するため必要
      'wp-i18n',  /// 翻訳関数 __() を使うため必要
      'wp-element', // アイコンオブジェクトの作成に必要
      'wp-primitives' // アイコンオブジェクトの作成に必要
    ),
    wp_get_theme()->get('Version'),
    true
  );
});
バリエーションを登録

作成した JavaScript ファイル(block-variations.js)に以下を記述して、registerBlockVariation() を使ってバリエーションを登録します。

この例ではカスタムアイコンを作成しています。

const { registerBlockVariation } = wp.blocks;
const { __ } = wp.i18n;

// カスタムアイコンの作成
const copyrightIcon = wp.element.createElement(
  wp.primitives.SVG,
  { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16" },
  wp.element.createElement(
    wp.primitives.Path,
    {
      d: "M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M8.146 4.992c.961 0 1.641.633 1.729 1.512h1.295v-.088c-.094-1.518-1.348-2.572-3.03-2.572-2.068 0-3.269 1.377-3.269 3.638v1.073c0 2.267 1.178 3.603 3.27 3.603 1.675 0 2.93-1.02 3.029-2.467v-.093H9.875c-.088.832-.75 1.418-1.729 1.418-1.224 0-1.927-.891-1.927-2.461v-1.06c0-1.583.715-2.503 1.927-2.503",
    }
  )
);

// 段落ブロック(core/paragraph)のバリエーションを登録
registerBlockVariation(
  'core/paragraph',  // 対象のブロック名
  {
    name: 'wdl/copyright',  // バリエーションを一意に識別するためのスラッグ
    title: __('Copyright', 'text-domain'), // バリエーションの名前(UI 上で表示されるラベル)
    description: 'Displays the copyright sign along with the start and current year',
    keywords:   ['copyright'],
    icon: copyrightIcon, // 作成したカスタムアイコンを指定
    // バリエーションが選ばれたときにブロックへ適用する初期値(属性)を指定
    attributes: {
      metadata: {
        // ブロックバインディング
        bindings: {
          content: {
            source: 'wdl/copyright',
            args: {
              starting_year: '2020',
            },
          },
        },
      },
    },
    // この判定が true の場合、UI 上で Copyright variation と認識される
    isActive: (attributes) => {
      // attributes.metadata.bindings.content.source が wdl/copyright かどうかで判定
      return attributes?.metadata?.bindings?.content?.source === 'wdl/copyright';
    },
  }
);

isActive に関数を使っていますが、単に isActive:['metadata'] としてもアクティブと判定されます。

上記のバリエーションを登録すると、ブロック挿入時の選択肢として表示され、カスタムソースにバインドされた段落ブロック(Copyright)を挿入できます。この例の場合、コピーマークのカスタムアイコンが表示されます。

ブロックを挿入すると、register_block_bindings_source() で指定したラベル「Copyright」が、挿入した位置に表示されます。

コードエディタービューに切り替えると、カスタムソースを段落ブロックにバインドしたブロックマークアップが確認できます。

フロント側では以下のように表示されます。

get_block_type_variations フックで登録

以下は上記とほぼ同じことを get_block_type_variations フック(PHP)で登録する例です。

この場合、カスタムアイコンは指定できないのでダッシュアイコンを指定しています。

また、isActive にアクティブ状態を判断するコールバックを渡すことはできないので、チェックする属性の配列を渡します。

add_filter('get_block_type_variations', function ($variations, $block_type) {

  if ('core/paragraph' !== $block_type->name) {
    return $variations;
  }

  $variations[] = array(
    'name' => 'wdl-copyright',
    'title' =>  __( 'Copyright', 'text-domain' ),
    'description' => 'Displays the copyright sign along with the current year',
    'keywords' => array('copyright'),
    'isDefault' => false,
    'icon' => 'info',  // ダッシュアイコンを指定(カスタムアイコンは指定できない)
    'attributes' => array(
      'metadata' => array(
        'bindings' => array(
          'content' => array(
            'source' => 'wdl/copyright',
            'args' => array(
              'starting_year' => '2020'
            )
          ),
        ),
      ),
    ),
    // 属性に metadata が含まれている場合に「Copyright」バリエーションと判定(関数は指定できない)
    'isActive'   => array(
      'metadata'
    ),
  );

  return $variations;
}, 10, 2);

複数バリエーションの登録

カスタムフィールドにバインドした複数のブロックのバリエーションを登録する例です。

あらかじめ以下の 3 つのメタキーを登録しておきます。

  • isbn: 段落ブロックの content 属性にバインド
  • amazon-url: ボタンブロックの url 属性にバインド
  • kinokuniya-url:ボタンブロックの url 属性にバインド

まず register_post_meta() を使って、投稿(post)に対してこれらのカスタムフィールドを登録します。

add_action('init', 'wdl_register_post_metas');

function wdl_register_post_metas() {
  register_post_meta(
    'post',
    'isbn',
    array(
      'show_in_rest'      => true,
      'single'            => true,
      'type'              => 'string',
      'sanitize_callback' => 'wp_strip_all_tags',  // 値をサニタイズ
    )
  );
  register_post_meta(
    'post',
    'amazon-url',
    array(
      'show_in_rest'      => true,
      'single'            => true,
      'type'              => 'string',
      'sanitize_callback' => 'esc_url_raw',  // URL としてサニタイズ
    )
  );
  register_post_meta(
    'post',
    'kinokuniya-url',
    array(
      'show_in_rest'      => true,
      'single'            => true,
      'type'              => 'string',
      'sanitize_callback' => 'esc_url_raw',  // URL としてサニタイズ
    )
  );
}

上記はほぼ同じオプションを使って登録しているので、コールバック関数は以下のように記述できます。

function wdl_register_post_metas() {

  $keys = ['isbn', 'amazon-url', 'kinokuniya-url'];
  foreach ($keys as $key) {
    register_post_meta('post', $key, array(
      'show_in_rest'      => true,
      'single'            => true,
      'type'              => 'string',
      'sanitize_callback' => $key === 'isbn' ? 'wp_strip_all_tags' : 'esc_url_raw',
    ));
  }
}
PHP で登録

次に、get_block_type_variations フックを使って段落ブロックとボタンブロックにバリエーションを追加します。get_block_type_variations のコールバック関数では、複数のブロックのバリエーションを定義したり、1つのブロックに複数のバリエーションを追加したりすることができます。

function wdl_block_type_variations($variations, $block_type) {

  if ('core/paragraph' === $block_type->name) {
    $variations[] = array(
      'name'       => 'book-isbn',
      'title'      => __('ISBN', 'text-domain'),
      'icon'       => 'book-alt',
      'attributes' => array(
        'metadata' => array(
          // ブロックバインディング
          'bindings' => array(
            'content' => array(
              'source' => 'core/post-meta',  // カスタムフィールド
              'args'   => array(
                'key' => 'isbn',
              ),
            ),
          ),
        ),
      ),
      // 元のブロックのインスタンスとバリエーションを区別するための情報
      'isActive'   => array('metadata'),
    );
  } elseif ('core/buttons' === $block_type->name) {
    $variations[] = array(
      'name'        => 'book-buttons',
      'title'       => __('Book Buttons', 'text-domain'),
      'icon'        => 'book-alt',
      // バリエーション挿入時の初期状態を定義するプロパティ
      'innerBlocks' => array(
        array(
          'core/button',
          array(
            'metadata' => array(
              // ブロックバインディング
              'bindings' => array(
                'url' => array(
                  'source' => 'core/post-meta',  // カスタムフィールド
                  'args'   => array(
                    'key' => 'amazon-url',
                  ),
                ),
              ),
            ),
            'text'     => __('Amazon', 'text-domain'),
            'linkTarget' => '_blank',
            'rel' => 'noopener'
          ),
        ),
        array(
          'core/button',
          array(
            'metadata' => array(
              // ブロックバインディング
              'bindings' => array(
                'url' => array(
                  'source' => 'core/post-meta',  // カスタムフィールド
                  'args'   => array(
                    'key' => 'kinokuniya-url',
                  ),
                ),
              ),
            ),
            'text'     => __('Kinokuniya', 'text-domain'),
            'linkTarget' => '_blank',
            'rel' => 'noopener'
          ),
        ),
      ),
    );
  }
  return $variations;
}
add_filter('get_block_type_variations', 'wdl_block_type_variations', 10, 2);
  • 段落ブロック(core/paragraph)
    • 「ISBN」バリエーションを追加し、カスタムフィールド isbn と連動させます。
  • ボタンブロック(core/buttons)
    • 「Book Buttons」バリエーションを追加し、innerBlocks プロパティで 2 つのボタン(Amazon / Kinokuniya)を初期配置しています。
    • innerBlocks は「バリエーション挿入時の初期状態を定義するプロパティ」で、挿入後は通常のボタンブロック同様、ユーザーが自由に追加・削除・編集可能です。
    • ※ 親ブロック core/buttons は属性(attributes)をほとんど持たないため、ここでは isActive 判定は行っていません(isActive 判定を設けても有効に機能しない)。

「Book Buttons」を core/buttons に登録する理由

「Book Buttons」バリエーションは core/buttons ブロックをベースにしています。

これは、ブロックインサーターに表示されるのが「ボタン(複数)」をまとめるコンテナブロックである core/buttons であり、個別の core/button は直接挿入できないためです。

core/button にもバリエーションを登録できますが、その場合はまず core/buttons を挿入してから内部にボタンを追加する必要があります。

一方で core/buttons にバリエーションを追加すれば、innerBlocks を使って複数のボタンをまとめて提供できるため、ユーザーはインサーターからワンクリックで「Amazon + Kinokuniya」のようなボタンセットを追加できます。

上記バリエーションを登録すると、ブロック挿入時の選択肢として表示され、インサーターから簡単にカスタムフィールドにバインド済みの段落ブロック(ISBN)やボタングループ(Book Buttons)を挿入できます。

以下は段落ブロック(ISBN)を挿入した例です。バリエーションの登録で、description を指定していないので、サイドバーのブロックの説明には、段落ブロックの説明と同じ内容が表示されています。

以下はボタングループ(Book Buttons)を挿入した例です。 isActive 判定を行っていないので、サイドバーには「Book Buttons」ではなく「ボタン」と表示されます。

コードエディターに切り替えると、以下のように表示されます。

JavaScript で登録

ブロックバリエーションは PHP だけでなく、JavaScript の registerBlockVariation() 関数を使って登録することもでき、この方法では、isActive にコールバック関数を指定できたり、独自アイコンを割り当てられたりするなど、より柔軟な制御が可能です(すでに説明済みで、繰り返しになりますが)。

スクリプトを読み込む

まず、テーマ内に /assets/js/block-variations.js を作成し、以下を functions.php に記述してエディター専用のスクリプトとして読み込みます。

add_action('enqueue_block_editor_assets', function () {
  wp_enqueue_script(
    'wdl-block-variations',
    get_theme_file_uri('assets/js/block-variations.js'),
    // 依存するスクリプトのハンドル名の配列
    array(
      'wp-blocks',    // バリエーション登録に必要
      'wp-dom-ready', // エディター初期化後に実行するため必要
      'wp-i18n',      // 翻訳関数 __() を使うため必要
    ),
    wp_get_theme()->get('Version'),
    true
  );
});

段落ブロックのバリエーションを登録

次に、block-variations.js に以下を記述して、ISBN を表示する段落ブロックを登録します。この例では description を追加しています。

const { registerBlockVariation } = wp.blocks;
const { __ } = wp.i18n;

// ISBN を表示する段落ブロックを登録
registerBlockVariation("core/paragraph", {
  name: "book-isbn",
  title: __("ISBN", "text-domain"),
  description: __("ISBN number for the Book.", "text-domain"),
  icon: "book-alt",
  attributes: {
    metadata: {
      bindings: {
        content: {
          source: "core/post-meta",
          args: { key: "isbn" },
        },
      },
    },
  },
  // metadata.bindings.content のソースが post-meta なら「ISBN」バリエーションと判定
  isActive: (attributes) => {
    return attributes?.metadata?.bindings?.content?.source === "core/post-meta";
  },
});

補足: isActive は isActive: ['metadata'] と書けば「metadata 属性が存在するかどうか」で判定することも可能です。

ボタンブロックのバリエーションを登録

次に、core/buttons に「Book Buttons」バリエーションを登録します。

innerBlocks を使うことで、Amazon と Kinokuniya の 2 つのボタンをあらかじめ含めた状態で挿入できるようになります。

registerBlockVariation("core/buttons", {
  name: "book-buttons",
  title: __("Book Buttons", "text-domain"),
  description: __("Links to purchase books on Amazon and Kinokuniya Online.", "text-domain"),
  icon: "book-alt",
  innerBlocks: [
    [
      "core/button",
      {
        metadata: {
          bindings: {
            url: {
              source: "core/post-meta",
              args: { key: "amazon-url" },
            },
          },
        },
        text: __("Amazon", "text-domain"),
        linkTarget: "_blank",
        rel: "noopener",
      },
    ],
    [
      "core/button",
      {
        metadata: {
          bindings: {
            url: {
              source: "core/post-meta",
              args: { key: "kinokuniya-url" },
            },
          },
        },
        text: __("Kinokuniya", "text-domain"),
        linkTarget: "_blank",
        rel: "noopener",
      },
    ],
  ],
  // isActive 判定用にダミー属性を追加
  attributes: {
    metadata: {},
  },
  // attributes の metadata の存在でアクティブとみなす
  isActive: ["metadata"],
});

判定用のダミー属性

core/paragraph など多くのブロックは block.json に attributes(属性)が定義されているので、そのまま isActive: ["metadata"] のように判定に使えます。

一方で、core/buttons は「ボタンのグループコンテナ」であり、実際のリンク先などの属性(attributes)は中に含まれる core/button にしかありません。つまり 親ブロックである core/buttons 自体には attributes が定義されていません。

そのため、普通に isActive: ["metadata"] を指定しても判定に使う対象が存在しません。

そこで解決策として、core/buttons 側に 判定用のダミー属性 を追加しています。

判定用のダミー属性は、最低限 { metadata: {} } のような空オブジェクトでも動作します。

以下は段落ブロック(ISBN)を挿入した例です。この例ではバリエーションの登録の際に description を設定したので、ISBN ブロックの説明が表示されています。

以下はボタングループ(Book Buttons)を挿入した例です。この例では isActive 判定を設定しているので、Book Buttons と認識されています。