Block Bindings API

Важно: Block Bindings API доступен только в WordPress 6.5 и выше.

Block Bindings API позволяет "привязывать" динамические данные к атрибутам блока, и эти значения затем отражаются в финальной HTML-разметке, которая выводится в браузер на фронтенде.

Пример - связать атрибут url блока Image с функцией, которая возвращает случайные изображения из внешнего API.

<!-- wp:image {
	"metadata":{
		"bindings":{
			"url":{
				"source":"my-plugin/get-random-images"
			}
		}
	}
} -->

Совместимые блоки и их атрибуты

Сейчас не все атрибуты блоков совместимы с bindings. Идёт работа по расширению совместимости, но на данный момент список такой:

Поддерживаемые блоки Поддерживаемые атрибуты
core/image id, url, title, alt, caption
core/heading content
core/paragraph content
core/button url, text, linkTarget, rel
core/navigation-link url
core/navigation-submenu url
core/post-date datetime

Источники ядра

В WordPress есть несколько встроенных источников block bindings, которые можно использовать без отдельной регистрации:

core/post-meta

Источник core/post-meta позволяет привязать атрибуты блока к полям мета-данных записи.

Требования:

  • Мета должна быть зарегистрирована с show_in_rest => true
  • Ключи мета не могут начинаться с подчёркивания (защищённые ключи недоступны)

Пример:

Сначала зарегистрируйте мета:

register_meta( 'post', 'my_custom_field', [
	'show_in_rest' => true,
	'single'       => true,
	'type'         => 'string',
] );

Затем привяжите к атрибуту блока:

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

core/post-data

С WP 6.9. Даёт доступ данным записи.

Доступные поля:

  • date - дата публикации записи.
  • modified - дата последнего изменения записи.
  • link - постоянная ссылка (permalink) записи.

Пример:

<!-- wp:paragraph {
	"metadata":{
		"bindings":{
			"content":{
				"source":"core/post-data",
				"args":{"field":"date"}
			}
		}
	}
} -->
<p>Fallback content</p>
<!-- /wp:paragraph -->

core/term-data

С WP 6.9. Даёт доступ к данным термина таксономии, когда доступен term context. Для корректной работы нужно, чтобы через block context были доступны termId и taxonomy.

Доступные поля

Поле Описание Пример
id ID термина 123
name Название термина Category Name
link URL архива термина https://example.com/category/news
slug Slug category-slug
description Описание термина A description of the category
parent ID родителя (для иерархических таксономий) 0
count Количество записей в термине 5

Пример использования

Показать названия терминов списком:

<!-- wp:terms-query {
	"termQuery":{
		"taxonomy":"category",
		"perPage":5
	}
} -->
<div class="wp-block-terms-query">
	<!-- wp:term-template {"layout":{"type":"default"}} -->
	<!-- wp:paragraph {
		"metadata":{
			"bindings":{
				"content":{
					"source":"core/term-data",
					"args":{"field":"name"}
				}
			}
		}
	} -->
	<p>Category Name</p>
	<!-- /wp:paragraph -->
	<!-- /wp:term-template -->
</div>
<!-- /wp:terms-query -->

Сделать ссылки на архивы терминов:

<!-- wp:terms-query {
	"termQuery":{
		"taxonomy":"post_tag",
		"perPage":10
		}
	} -->
<div class="wp-block-terms-query">
	<!-- wp:term-template {"layout":{"type":"default"}} -->
	<!-- wp:paragraph {
		"metadata":{
			"bindings":{
				"content":{
					"source":"core/term-data",
					"args":{"field":"name"}
				}
			}
		}
	} -->
	<p><a href="#">Tag Name</a></p>
	<!-- /wp:paragraph -->
	<!-- /wp:term-template -->
</div>
<!-- /wp:terms-query -->

Требования к контексту

Источник core/term-data работает в таких контекстах:

  1. Любой блок, который предоставляет term context - например core/term-template, или кастомные блоки, которые передают termId и taxonomy через block context.

  2. Блоки навигации - есть специальная обработка обратной совместимости для core/navigation-link и core/navigation-submenu (они читают из атрибутов блока вместо context)

core/pattern-overrides

Источник core/pattern-overrides позволяет экземплярам паттернов иметь переопределения контента на уровне конкретного экземпляра.

Это пригодится там, где нужно разрешить менять вложенные блоки, сохраняя весь паттерн нетронутым. Подробнее здесь.

Как это работает:

  • В блоках внутри паттерна указывается, какие атрибуты можно переопределять, через metadata.bindings
  • Каждый экземпляр паттерна хранит значения override в атрибуте content
  • Binding связывает атрибут блока со значением override, используя metadata.name блока как ключ
  • Структура контекста: pattern/overrides -> {block_name} -> {attribute_name}

Пример:

Внутри паттерна пометьте блок, контент которого нужно изменть, как переопределяемый:

<!-- wp:paragraph {
	"metadata":{
		"name":"custom-heading"
		"bindings":{
			"content":{
				"source":"core/pattern-overrides"
			}
		}
	}
} -->
<p>Default text</p>
<!-- /wp:paragraph -->

При вставке паттерна пользователь сможет переопределить контент для этого блока в текущем экземпляре паттерна:

<!-- wp:block {
	"ref":123,
	"content":{
		"custom-heading":{
			"content":"My custom heading text"}
		}
	} / -->

В этом примере:

  • custom-heading - уникальный идентификатор для блока core/paragraph в системе core/pattern-overrides.
  • Он используется как ключ: pattern/overrides -> custom-heading -> content.
  • Это позволяет иметь несколько одинаковых блоков (например, несколько core/paragraph) в одном паттерне и задавать для каждого свои override.

Расширение поддерживаемых атрибутов

С WP 6.9. Разработчики могут расширить список поддерживаемых атрибутов через фильтр block_bindings_supported_attributes.

Доступны 2 фильтра:

Пример добавления поддержки caption у Image:

add_filter(
	'block_bindings_supported_attributes_'.'core/image',
	function ( $supported_attributes ) {
		$supported_attributes[] = 'caption';
		return $supported_attributes;
	}
);

Пример для кастомного блока:

add_filter(
	'block_bindings_supported_attributes_'.'my-plugin/my-block',
	function ( $supported_attributes ) {
		$supported_attributes[] = 'title';
		$supported_attributes[] = 'description';
		return $supported_attributes;
	}
);

Этот фильтр также влияет на то, какие блоки и атрибуты доступны для Pattern Overrides, потому что обе функции используют общую конфигурацию supported attributes.

Доступ к значениям Pattern Override в динамических блоках

Если вы делаете динамический блок, который поддерживает Pattern Overrides, вы можете читать override-значения внутри render_callback. Блок Pattern (core/block) передаёт override-значения вложенным блокам через контекст pattern/overrides.

Шаг 1. Зарегистрировать блок с нужным context и supported attributes

add_action( 'init', function() {
	add_filter(
		'block_bindings_supported_attributes_' . 'my-plugin/my-block',
		function ( $supported_attributes ) {
			$supported_attributes[] = 'title';
			$supported_attributes[] = 'description';
			return $supported_attributes;
		}
	);

	register_block_type( 'my-plugin/my-block', [
		'uses_context' => [ 'pattern/overrides' ],
		'render_callback' => 'my_block_render_callback',
		'attributes' => [
			'title'       => [ 'type' => 'string' ],
			'description' => [ 'type' => 'string' ],
			'metadata'    => [ 'type' => 'object' ],
		],
	] );
} );

Шаг 2. Получить override-значения в render callback

Override лежат в $block->context['pattern/overrides'] как ассоциативный массив: ключи - это metadata.name, значения - массивы переопределённых атрибутов.

function my_block_render_callback( $attrs, $content, $block ) {
	$block_name = $attrs['metadata']['name'] ?? '';

	$overr = $block->context['pattern/overrides'][ $block_name ] ?? [];

	$title = ( $overr['title'] ?? '' ) ?: $attrs['title'];
	$desc  = ( $overr['description'] ?? '' ) ?: $attrs['description'];

	return strtr(
		'<div class="my-block">
			<h3>{{title}}</h3>
			<p>{{desc}}</p>
		</div>',
		[
			'{{title}}' => esc_html( $title ),
			'{{desc}}'  => esc_html( $desc ),
		]
	);
}

Ключевые моменты:

  • uses_context - блок должен объявить pattern/overrides, чтобы получать данные override.
  • metadata.name` - у каждого переопределяемого экземпляра блока есть уникальное имя в$attributes['metadata']['name']`.
  • Пустая строка '' в overrides означает "сбросить к значению по умолчанию", это нужно учитывать.
  • Всегда делайте fallback на $attributes, если блок не внутри pattern или overrides не заданы.

Кастомный источник

Чтобы зарегистрировать источник, нужно определить минимум: name, label и callback, который получает значение и возвращает его для атрибута блока.

После регистрации любой поддерживаемый блок может настроить metadata.bindings так, чтобы читать значение из этого источника.

Регистрацию можно делать на сервере (PHP) и в редакторе (JS) - оба варианта могут сосуществовать.

Label, заданный на сервере, будет переопределён label, заданным в редакторе.

Серверная регистрация

Серверная регистрация позволяет назначить callback, который выполняется на фронтенде для привязанного атрибута.

Функция: register_block_bindings_source( $name, $args )

  • name: string - уникальный ID источника
  • args: array, включая:

    • label: string - человекочитаемое имя
    • uses_context: array - какой block context передавать в callback (опционально)
    • get_value_callback: callable - выполняется при рендере связанного блока.
      Принимает ( $source_args, $block, $attribute_name ). Значение можно переопределить фильтром block_bindings_source_value.

Вызывать нужно на хуке init. Пример:

add_action( 'init', function() {
	register_block_bindings_source(
		'wpmovies/visualization-date',
		[
			'label'              => 'Visualization Date',
			'uses_context'       => [ 'postId' ],
			'get_value_callback' => function( $source_args, $block ) {
				$post_id = $block->context['postId'];
				if( isset( $source_args['key'] ) ){
					return get_post_meta( $post_id, $source_args['key'], true );
				}
			},

		]
	);
} );

Этот пример требует зарегистрированной post_meta. Также можно использовать фильтр, чтобы вернуть дефолтное значение, которое будет отображаться дальше.

add_action( 'init', function() {
	register_meta( 'post', 'wp_movies_visualization_date', [
		'label'        => 'Movie visualization date',
		'type'         => 'string',
		'show_in_rest' => true,
		'single'       => true,
	] );
} );
  • Клюи начинающиеся с _, например _example_key работать не будут.
  • meta должна быть зарегистрирована с show_in_rest = true.

Фильтр block_bindings_source_value

С WP 6.7. Значение из get_value_callback можно изменить через фильтр block_bindings_source_value.

Параметры фильтра:

  • value - значение для фильтрации.
  • name - имя источника.
  • source_args - аргументы источника.
  • block_instance - объект экземпляра блока.
  • attribute_name - имя атрибута.

Пример:

add_filter( 'block_bindings_source_value', 'format_visual_date', 10, 2 );
function format_visual_date( $value, $name ) {
	if ( $name !== 'wpmovies/visualization-date' ) {
		return $value;
	}

	return $value
		? date( 'm/d/Y', strtotime( $value ) )
		: date( 'm/d/Y' );
}

Примеры в ядре (server registration)

  • Post Meta
  • Post Data
  • Term Data
  • Pattern overrides
  • Тема Twenty Twenty-Five (functions.php)

Регистрация в редакторе (в js)

С WP 6.7. Регистрация на клиенте позволяет определить, что делать при получении значения и при редактировании значения.

Функция: registerBlockBindingsSource( args )

  • args (object):

    • name: string - уникальное машинное имя.
    • label: string - человекочитаемое имя (опционально).
    • usesContext: array - требуемый block context (опционально).
    • getValues: function - получить значения (опционально).
    • setValues: function - сохранить значения (опционально).
    • canUserEditValue: function - можно ли пользователю редактировать (опционально).
    • getFieldsList: function - список доступных полей для UI (опционально, начиная с WP 6.9).

Пример показывает мета-дату в редакторе, а если мета нет - показывает сегодняшнюю дату. Пользователь может редактировать значение. (Внимание: пример не форматирует ввод как дату.)

import { registerBlockBindingsSource } from '@wordpress/blocks';
import { store as coreDataStore } from '@wordpress/core-data';

registerBlockBindingsSource( {
	name: 'wpmovies/visualization-date',
	label: 'Visualization Date',
	usesContext: [ 'postType' ],
	getValues( { select, context } ) {
		let wpMoviesVisualizationDate;
		const { getEditedEntityRecord } = select( coreDataStore );
		if ( context?.postType && context?.postId ) {
			wpMoviesVisualizationDate = getEditedEntityRecord(
				'postType',
				context?.postType,
				context?.postId
			).meta?.wp_movies_visualization_date;
		}
		if ( wpMoviesVisualizationDate ) {
			return {
				content: wpMoviesVisualizationDate,
			};
		}

		return {
			content: new Date().toLocaleDateString( 'en-US' ),
		};
	},
	setValues( { select, dispatch, context, bindings } ) {
		dispatch( coreDataStore ).editEntityRecord(
			'postType',
			context?.postType,
			context?.postId,
			{
				meta: {
					wp_movies_visualization_date: bindings?.content?.newValue,
				},
			}
		);
	},
	canUserEditValue( { select, context } ) {
		return true;
	},
} );

getValues()

Вызывается при загрузке блока. Аргумент - объект с полями:

  • bindings - объект bindings для конкретного источника (ключи - атрибуты)
  • clientId - client ID блока
  • context - текущий block context (из usesContext)
  • select - селекторы указанного data store

Функция должна вернуть объект вида:

{ 'атрибут_блока': значение }

setValues()

Обновляет значения источника для привязанного блока. Аргумент - объект с полями:

  • bindings - объект bindings, содержит newValue (ввод пользователя)
  • clientId - client ID блока
  • context - block context
  • dispatch - action creators store
  • select - селекторы store

getFieldsList()

С WP 6.9.

Позволяет кастомным источникам появляться в выпадающем списке UI Block Bindings. При выборе опции источник автоматически привязывается к атрибуту с args выбранного поля.

Возвращает массив объектов полей, каждый из которых:

  • label: string - подпись в списке (по умолчанию label источника)
  • type: string - тип значения (должен совпадать с типом атрибута)
  • args: object - аргументы источника, применяемые при выборе поля

Пример:

registerBlockBindingsSource( {
	name: 'my-plugin/custom-fields',
	label: 'Custom Fields',
	getFieldsList() {
		return [
			{
				label: 'Author Name',
				type: 'string',
				args: {
					field: 'author_name',
				},
			},
			{
				label: 'Publication Year',
				type: 'string',
				args: {
					field: 'publication_year',
				},
			},
			{
				label: 'Page Count',
				type: 'number',
				args: {
					field: 'page_count',
				},
			},
		];
	},
	getValues( { bindings } ) {
		// Implementation to retrieve values based on args.field
	},
} );

После этого пользователь увидит "Author Name", "Publication Year", "Page Count" в UI dropdown при привязке атрибутов к вашему источнику.

Подсказка: посмотрите пример Editor Bindings в репозитории Block Development Examples.

Примеры в ядре (editor registration)

  • Post Meta (пример в Gutenberg)
  • Pattern overrides (пример в Gutenberg)

Удаление регистрации источника

Примечание: Начиная с WordPress 6.7.

unregisterBlockBindingsSource удаляет источник по имени:

import { unregisterBlockBindingsSource } from '@wordpress/blocks';

unregisterBlockBindingsSource( 'plugin/my-custom-source' );

Получение всех источников

Примечание: Начиная с WordPress 6.7.

getBlockBindingsSources возвращает все зарегистрированные источники:

import { getBlockBindingsSources } from '@wordpress/blocks';

const registeredSources = getBlockBindingsSources();

Получение конкретного источника

Примечание: Начиная с WordPress 6.7.

getBlockBindingsSource возвращает источник по имени:

import { getBlockBindingsSource } from '@wordpress/blocks';

const blockBindingsSource = getBlockBindingsSource( 'plugin/my-custom-source' );

Block Bindings Utils

Примечание: Начиная с WordPress 6.7.

useBlockBindingsUtils - хук с двумя помощниками, который упрощает редактирование metadata.bindings.

Он принимает clientId (string). Если не передан, используется текущий client ID из контекста.

Пример:

import { useBlockBindingsUtils } from '@wordpress/block-editor';

const { updateBlockBindings } = useBlockBindingsUtils( 'my-block-client-id-12345' );
...

updateBlockBindings

Похож на updateBlockAttributes, позволяет создавать, обновлять или удалять конкретные привязки.

import { useBlockBindingsUtils } from '@wordpress/block-editor';

const { updateBlockBindings } = useBlockBindingsUtils();

function updateBlockBindingsURLSource( url ) {
	updateBlockBindings( {
		url: {
			source: 'myplugin/new-source',
		},
	} );
}

function removeBlockBindingsURLSource() {
	updateBlockBindings( { url: undefined } );
}

removeAllBlockBindings

Удаляет все привязки, убирая metadata.bindings у блока.

import { useBlockBindingsUtils } from '@wordpress/block-editor';

const { removeAllBlockBindings } = useBlockBindingsUtils();

function clearBlockBindings() {
	removeAllBlockBindings();
}