﻿---
title: "PHP-only block registration: блоки без JavaScript"
description: "Регистрация блоков только на PHP через supports.autoRegister в WordPress 7.0: обязательный render_callback, автогенерация контролов, поддерживаемые типы атрибутов и ограничения подхода."
---

С версии WordPress 7.0 блок можно зарегистрировать одним PHP-вызовом — без `block.json`, без сборки JavaScript и без `registerBlockType` на клиенте. Флаг `supports.autoRegister` включает режим, в котором ядро само создаёт запись блока в редакторе и само рисует контролы атрибутов в боковой панели. Такой блок всегда рендерится на сервере через `render_callback`.

Подход рассчитан на **серверные блоки**: вывод связанных записей, виджет-подобные настройки, блоки темы, которые раньше делали шорткодом. Он не заменяет клиентскую модель блоков и никогда не сравнится с ней по возможностям — интерактивные блоки по-прежнему пишутся на JavaScript.

## Минимальный блок

`register_block_type` получает имя блока и массив настроек. Обязательны два элемента: `render_callback` и `supports.autoRegister => true`.

```php
add_action( 'init', 'myplugin_register_blocks' );

function myplugin_register_blocks() {
	register_block_type(
		'myplugin/notice',
		array(
			'title'          => __( 'Notice', 'myplugin' ),
			'category'       => 'design',
			'attributes'     => array(
				'text' => array(
					'label'   => __( 'Текст', 'myplugin' ),
					'type'    => 'string',
					'default' => __( 'Обратите внимание', 'myplugin' ),
				),
				'level' => array(
					'label'   => __( 'Уровень', 'myplugin' ),
					'type'    => 'string',
					'enum'    => array( 'info', 'warning', 'error' ),
					'default' => 'info',
				),
			),
			'render_callback' => 'myplugin_render_notice',
			'supports'        => array(
				'autoRegister' => true,
				'html'         => false,
			),
		)
	);
}

function myplugin_render_notice( $attributes ) {
	$level = in_array( $attributes['level'], array( 'info', 'warning', 'error' ), true )
		? $attributes['level']
		: 'info';

	return sprintf(
		'<div %1$s><p class="notice notice--%2$s">%3$s</p></div>',
		get_block_wrapper_attributes(),
		esc_attr( $level ),
		esc_html( $attributes['text'] )
	);
}
```

Что здесь важно:

- **`render_callback` обязателен.** Без него блок не отрисуется: у PHP-only блока нет сохранённой разметки, только серверный рендер.
- **`get_block_wrapper_attributes()`** отдаёт классы и стили, которые редактор ждёт на обёртке блока. Без него поддержка цветов, отступов, типографики и пользовательские классы не применятся, хотя сами `supports` формально включены.
- **`supports.html: false`** убирает вкладку «Дополнительно → HTML-элемент», которая для серверного блока бессмысленна.

## Какие контролы генерируются

Ядро строит контрол по типу атрибута:

| Тип атрибута | Контрол в боковой панели |
| --- | --- |
| `string` | текстовое поле |
| `string` + `enum` | выпадающий список |
| `number`, `integer` | числовое поле |
| `boolean` | переключатель |

Это весь поддерживаемый набор на 7.0. Медиафайлы, `rich text`, многострочный текст, дата и цвет как отдельные поля не поддерживаются.

Дополнительные правила:

- **`label` переводим.** Подпись контрола берётся из атрибута `label` и оборачивается в `__()` — без него в панели будет техническое имя атрибута.
- **Только несурced-атрибуты.** Атрибут должен сохраняться в JSON-комментарии блока, а не извлекаться из HTML (`source`). Для sourced-атрибутов контрол не создаётся.
- **`role: local` — без контрола.** Атрибуты с ролью `local` не сохраняются в контенте (это состояние редактора), поэтому панель их не показывает.
- **`enum` без пар «ключ → подпись».** В списке выводятся сами значения (`info`, `warning`), локализовать их нельзя. Если нужны человеческие подписи — выносите выбор в отдельный атрибут с `enum` из чисел и маппинг в PHP-рендере.

## Ограничения, о которых стоит знать заранее

**Нет `save`.** Блок не хранит свою разметку в `post_content` — только атрибуты. Сохранить HTML на этапе редактирования (как у статических блоков) нельзя, и в ядре не планируют это добавлять: пришлось бы решать задачу надёжного извлечения атрибутов из HTML.

**Нет внутренних блоков.** `InnerBlocks` в PHP-only блоках недоступен. Контейнер с вложенными колонками или группами так не собрать — для этого нужен обычный клиентский блок. Практический потолок подхода — «серверный виджет»: один блок, несколько настроек, готовый вывод.

**Каждое изменение — поход на сервер.** Правка атрибута вызывает повторный рендер через REST. Для блока, который тянет тяжёлый запрос, это заметно замедляет редактор: кэшируйте выборку и не запускайте дорогие запросы в `render_callback` без нужды.

**Контекст поста при повторном рендере.** `uses_context` с `postId` заполняется при первом рендере, но не при последующих вызовах из редактора через REST (тикет #65331, перенесён в Gutenberg #78619). Если блоку нужен ID записи — передавайте его атрибутом или получайте иначе, не полагайтесь на контекст.

**Версия важна.** Флаг появился в 7.0 (первое рабочее состояние — 7.0-beta3). На более старом ядре неизвестный ключ в `supports` игнорируется молча, и блок просто не появится в редакторе. Проверяйте версию явно:

```php
if ( version_compare( get_bloginfo( 'version' ), '7.0', '<' ) ) {
	return; // на старом ядре блок регистрируем старым способом
}
```

Публичной функции вида `current_theme_supports()` для проверки `autoRegister` нет — остаётся сверка версии.

## Когда подход уместен

- **Классические темы.** Блок даёт нормальные контролы вместо шорткода: пользователь видит настройки в панели, а не атрибуты в квадратных скобках.
- **Серверные данные.** Вывод последних записей, курса валют, списка услуг из настроек — то, что бессмысленно хранить в контенте.
- **Блоки темы под один проект.** Авторская подпись, CTA-секция, блок с фиксированной вёрсткой и парой настроек.
- **Миграция шорткодов.** Быстрый путь перевести шорткод в блок, не поднимая сборку JS.

Не подходит для интерактивных блоков (табы, слайдеры, аккордеоны с состоянием в редакторе), для контейнеров с вложенностью и для блоков, где важна мгновенная реакция интерфейса без обращения к серверу.

## Что проверить после регистрации

- Блок виден в инсертере и вставляет нужную разметку на фронте.
- Контролы появились в боковой панели, подписи переведены.
- Стили из `supports` (цвет, отступы, ширина) применяются к обёртке.
- Повторное открытие записи сохраняет значения атрибутов.
- Рендер не делает тяжёлых запросов: откройте запись в редакторе и посмотрите время ответа REST-запроса блока.

## Связанные страницы

- [Блочный редактор WordPress: добавление контента блоками](https://wpcraft.ru/kb/stacks/wordpress/block-editor/editor-blocks.md)
- [Блок Custom HTML](https://wpcraft.ru/kb/stacks/wordpress/block-editor/custom-html-block.md)
- [Паттерны (Block Patterns)](https://wpcraft.ru/kb/stacks/wordpress/themes/patterns.md) — статичные композиции блоков без серверного рендера
- [PHP в паттернах](https://wpcraft.ru/kb/stacks/wordpress/themes/patterns/php.md) — где выполняется PHP в паттернах и почему это не то же самое

## Материалы и источники

- [PHP-only block registration (Make WordPress Core, 3 марта 2026)](https://make.wordpress.org/core/2026/03/03/php-only-block-registration/)
- [Тикет #64639 — реализация `autoRegister`](https://core.trac.wordpress.org/ticket/64639)
- [Тикет #65331 — контекст `postId` при повторном рендере](https://core.trac.wordpress.org/ticket/65331)
- [Gutenberg #78619](https://github.com/WordPress/gutenberg/issues/78619)