WordPressブロック開発 ブロックのバリエーションを作成し、投稿の抜粋をバインディングする

段落ブロックのバリエーションを作成し、投稿の抜粋をバインディングしてみます。

ブロックの雛形を生成する

npx @wordpress/create-block@latest bound-excerpt --template @block-developer-cookbook/bound-excerpt

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

サーバー側でカスタムブロックバインディングソースを定義する。まず、ブロックにバインディングするための新しいデータソースを作成する。

bound-excerpt.php

/**
 * Register a custom block bindings source for post excerpts.
 * This allows blocks to bind their content to a post's excerpt field.
 */
add_action(
	'init',
	function () {
		register_block_bindings_source(
			'block-developer-cookbook/excerpt',
			array(
				'label'              => 'block-developer-cookbook',
				'get_value_callback' => __NAMESPACE__ . '\retrieve_excerpt_binding',
				'uses_context'       => array('postId'), // Required context from block.
			)
		);
	}
);

register_block_bindings_source()

ブロックバインディングにおけるカスタムデータソースを登録する関数。ブロックにバインディングするための新しいデータソースを作成し、それを利用して投稿の抜粋をブロックに表示する

  1. 第一引数:カスタムデータソースの名前(スラッグ)。他のブロックで利用され、バインディングを設定する際に参照される
  2. 第二引数:データソースの設定情報を含む配列
    • label:このデータソースの名前やラベルとして表示
    • get_value_callback:データソースから値を取得するためのコールバック関数を指定
    • uses_context => array('postId')
      • データソースがどのコンテキストに基づいて動作するかを指定。'postId' を指定した場合、このデータソースがブロック内で使用される際に、postId が必要であることを示す

カスタムブロックバインディング に使用されるコールバック関数を定義する。この関数は、ブロックが 投稿の抜粋(excerpt)フィールドにバインディングする際に、抜粋を取得するために使用される。

/**
 * Retrieves the post excerpt for use in block bindings.
 * This callback is used by blocks that bind to the post excerpt.
 *
 * @param array    $source_args    The source arguments.
 * @param WP_Block $block_instance The block instance.
 * @return string The post excerpt.
 */
function retrieve_excerpt_binding($source_args, $block_instance) {
	$post_id      = $block_instance->context['postId'];
	$current_post = get_post($post_id);
	return $current_post->post_excerpt;
}

retrieve_excerpt_binding()

ブロックが投稿の 抜粋 を取得するために使われることを目的に定義されたコールバック関数

引数

  1. $source_args: データソースからの引数を含む配列。このコールバック関数内では実際には使用されていませんが、バインディングを行うために他のメタデータを渡す場合などに使われる
  2. $block_instance: 現在のブロックのインスタンスを表すオブジェクト。ブロックのコンテキストなどの情報が含まれている。ブロックのコンテキストには、例えば 投稿ID や ユーザーID など、ブロックがどのデータを参照するかを決定するための情報が格納されている
  3. $block_instance->context['postId']:現在のブロックが必要とするコンテキスト情報を含む配列の中から投稿IDを取得する
  4. get_post($post_id)
    • get_post() は、指定された投稿IDに関連する投稿オブジェクトを返す WordPress の関数。このオブジェクトには、投稿のすべての情報(タイトル、内容、抜粋、メタデータなど)が格納される。
    • get_post($post_id) を使用して、ブロックがバインディングしている投稿の情報を取得。
  5. $current_post->post_excerpt
    • 投稿オブジェクト $current_post の中には、post_excerpt というプロパティがあり、このプロパティには投稿の 抜粋 が格納されている
    • post_excerpt は、投稿の要約や簡潔な説明文として表示される部分で、通常は投稿エディタで指定された内容。

抜粋のブロックバリエーションを作成する

カスタムバインディングソースを接続するブロックを作成する。

bound-excerpt.js

/**
 * Register a block variation to make it easier to assign the custom binding.
 */
registerBlockVariation( 'core/paragraph', {
	name: 'block-developer-cookbook/excerpt',
	title: 'Bound Excerpt',
	icon,
	description:
		'Mange the post excerpt directly in a block using a custom binding.',
	isActive: [ 'metadata.bindings.content.source' ],
	attributes: {
		metadata: {
			bindings: {
				content: {
					source: 'block-developer-cookbook/excerpt',
				},
			},
		},
	},
	scope: [ 'inserter' ],
} );

ブロックエディターでの値の読み取りと書き込み

関数を使用してクライアント側でも値の更新を反映させる

bound-excerpt.js

/**
 * Register the custom bindings so it can be edited in the block editor.
 */
registerBlockBindingsSource( {
	label: 'Post Excerpt', // Human readable name in the UI
	name: 'block-developer-cookbook/excerpt', // Source name. MUST match the name defined in PHP.
	getValues( { select } ) {
		return {
			content:
				select( 'core/editor' ).getEditedPostAttribute( 'excerpt' ),
		};
	},

	setValues( { dispatch, bindings } ) {
		dispatch( 'core/editor' ).editPost( {
			excerpt: bindings?.content?.newValue,
		} );
	},

	canUserEditValue( { select, context } ) {
		return true;
	},
} );

registerBlockBindingsSource

Gutenberg エディタ内で使用する カスタムバインディングソース を登録

  1. label: カスタムバインディングのラベル。
  2. name: バインディングの一意な名前。この名前は PHP 側で定義した名前(block-developer-cookbook/excerpt)と一致させる
  3. getValues:ブロックエディタ内で現在のデータを取得するための関数。この関数が返す値は、ブロックがそのデータをどのように表示するかに影響する
    • select: Gutenberg のエディタストアからデータを取得するための関数。ここでは、core/editor ストアを使って、現在編集中の投稿の 抜粋 を取得
    • getEditedPostAttribute( 'excerpt' ): 編集中の投稿の抜粋を取得
  4. setValues:ブロック内でユーザーがデータを編集した際にその変更を 保存 するための関数。この関数が呼ばれると、ブロック内での変更が実際の投稿に反映される
    • dispatch: Gutenberg のエディタストアに対してアクションを送るための関数。この場合、投稿の内容を更新するために使用。
    • bindings?.content?.newValue: bindings は現在のバインディングの値を保持するオブジェクトで、ここでは content に対応する新しい値(ユーザーが編集した抜粋の内容)を取り出している。
    • bindings?.content?.newValue: 編集された抜粋の新しい値を取得し、それを投稿の excerpt フィールドに設定。
  5. canUserEditValue:ユーザーがそのバインディングの値を編集できるかどうかを判定する関数。この関数は、例えばユーザーの権限に基づいて編集可能かどうかを判断するために使用。
    • true を返す場合、すべてのユーザーがこの抜粋フィールドを編集できることを意味

ブロックのコンテキスト

ブロックのコンテキスト(Block Context)は、WordPress の Gutenberg エディタにおける ブロック が動作するために必要な コンテキスト情報。

コンテキスト情報の主な例

  • postId: 投稿やページのID。ブロックがどの投稿またはページに挿入されているか
  • author: 投稿の著者情報。著者名や著者のIDなどの情報を取得するために使用
  • postType: 投稿タイプ(postpage、カスタム投稿タイプなど)
  • taxonomy: 投稿が所属するタクソノミー(カテゴリやタグなど)
  • isPreview: 投稿がプレビュー中かどうかを示すフラグ
  • isEditor: 投稿がエディタ(Gutenbergエディタ)で表示されているかどうか
  • current_user: 現在ログインしているユーザーの情報

$block_instance

$block_instance は、Gutenbergのブロック のインスタンスを指す変数であり、ブロックに関連する情報(プロパティやメソッド)を持つオブジェクト。ただし、$block_instance は WordPress の内部で生成され、通常、ブロックのレンダリングバインディング に関する処理が行われる際に使用される

ブロックエディタ内でブロックがレンダリングされるときJavaScript側からブロックの属性を操作するとき に生成され、その中でコンテキスト情報(例えば、postIdcurrent_user)などを取得するために使用される

このオブジェクトは、特定のブロックが処理される際に自動的に生成される。

  • ブロックが挿入される: エディタ内でユーザーがブロックを挿入したとき、そのブロックのインスタンスが作成
  • ブロックがサーバーサイドでレンダリングされる: サーバーサイドでブロックが表示される際、そのブロックの コンテキスト情報(投稿IDやユーザー情報など)を基に処理

ブロックインスタンスの構成要素

  • context: 現在のブロックがどのデータに関連しているかを示す情報(例えば、投稿IDやカスタムフィールドなど)
  • attributes: ブロックに設定された属性(ブロックの内容や設定)
  • blockName: ブロックの種類(例えば、core/paragraph

getValues関数 / select関数

select( 'core/editor' ).getEditedPostAttribute( 'excerpt' ) の部分は、WordPress の Gutenberg エディタ のデータストアにアクセスし、現在編集中の投稿の抜粋を取得するためのコード。

select は、現在の投稿データや、ブロックの状態、エディタの設定などを管理するデータストア からデータを取得するための関数。

core/editor というストアは、WordPress Gutenberg エディタ の編集に関連するデータを保持している。具体例:

  • 現在編集中の 投稿の属性(タイトル、本文、抜粋など)
  • 投稿の 状態(公開、下書きなど)
  • ブロックの内容(エディタ内で配置されているブロックの情報)

getEditedPostAttribute は、core/editor ストアから編集中の投稿に関する特定の属性を取得するメソッド。'excerpt' という引数を渡すことで、投稿の抜粋 フィールドに格納されている値を取得している。

getEditedPostAttributeが取得できる属性

  • 'title' — 投稿のタイトル
  • 'content' — 投稿の本文
  • 'excerpt' — 投稿の抜粋
  • 'status' — 投稿の状態(公開、下書き、など)
  • など
getValues( { select } ) {
    return {
        content: select( 'core/editor' ).getEditedPostAttribute( 'excerpt' ),
    };
}
  1. getValues: ブロックのデータを取得する役割を持つメソッド
  2. select( 'core/editor' ): Gutenberg のエディタストア(core/editor )からデータを取得するための関数
  3. getEditedPostAttribute( 'excerpt' ): 現在編集中の投稿の 抜粋 フィールドの値を取得するメソッド

setValues関数 / dispatch

setValues 関数内で使われている dispatch( 'core/editor' ).editPost の部分は、Gutenberg エディタ内で ブロック内での変更 を実際の 投稿データ に反映させるためのコード。

dispatch は、Gutenberg の データストア に対して アクション を送信するための関数です。アクションは、データを変更するための指示のこと。ストア(core/editor)に対してデータを変更するためのアクションを dispatch を使って送信する。

core/editor は、現在編集中の投稿に関連するデータを保持する Gutenberg の エディタストア

editPost は、core/editor ストアに対して 投稿の属性を更新 するためのメソッドです。これを使うことで、編集中の投稿のデータを実際に変更することができる。

dispatch( 'core/editor' ).editPost( {
    excerpt: bindings?.content?.newValue,
} );

上記はeditPost メソッドを使って、編集中の投稿の 抜粋(excerpt) を更新している。

bindings?.content?.newValue
  1. bindings: ブロックが現在バインディングしているデータのオブジェクト。ここでは、ブロックが 投稿の抜粋 とバインドされている
  2. bindings.content: content は、バインディングされたデータのフィールド名。この場合、ブロック内で編集される 抜粋 がこのフィールドに格納されている。
  3. newValue: ブロック内でユーザーが入力した新しい値。ブロックの内容が変更されると、この値が更新される

参考:https://blockdevelopercookbook.com/recipes/binding-the-excerpt-to-a-block/