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 работает в таких контекстах:
-
Любой блок, который предоставляет term context - например
core/term-template, или кастомные блоки, которые передаютtermIdиtaxonomyчерез block context. - Блоки навигации - есть специальная обработка обратной совместимости для
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 фильтра:
- block_bindings_supported_attributes - общий фильтр (получает массив поддерживаемых атрибутов и имя типа блока)
- block_bindings_supported_attributes_(block_type) - динамический фильтр для конкретного типа блока (например,
block_bindings_supported_attributes_core/image)
Пример добавления поддержки 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 contextdispatch- action creators storeselect- селекторы 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();
}