Как добавить метаполя поста на боковую панель документа Gutenberg
В этом посте мы рассмотрим, как добавить пользовательские мета-настройки поста на боковую панель Gutenberg на вкладке «Документ», вместо того, чтобы полагаться на добавление мета-полей традиционным (и, честно говоря, гораздо более ручным) способом.
Если вы работали с WordPress задолго до того, как появился Gutenberg, вы, вероятно, знакомы с добавлением пользовательских метаданных записей с помощью [add_meta_box](https://developer.wordpress.org/reference/functions/add_meta_box/)(). Эта функция позволяет вам добавлять мета-поле с вашим пользовательским содержимым внизу или сбоку при редактировании сообщения. Этот метод все еще работает, в том числе и в редакторе Гутенберга!
Однако это выглядит немного не так по сравнению с остальным содержимым боковой панели Гутенберга. И не говоря уже о том, что вам нужно будет вручную написать код ввода (флажок, ввод текста и т. д.) с помощью PHP, а также написать дополнительный код, чтобы сохранить их при обновлении сообщения. И если вы хотите, чтобы ваши мета-настройки публикации были динамическими (скажем, вы хотели скрыть поле, если не было включено какое-то другое поле), тогда вам пришлось бы вручную ставить скрипт в очередь и да, как вы уже догадались, вручную обрабатывать динамическую логику. скрывать и показывать. Теперь все это устарело и стало проще благодаря новому редактору Gutenberg на основе Javascript. Мы можем довольно легко сделать что-то вроде этого:
Процесс
Процесс выглядит следующим образом:
- Мы регистрируем каждый пользовательский мета-ключ записи, который хотим добавить в PHP, с помощью
[register_post_meta](https://developer.wordpress.org/reference/functions/register_post_meta/)(), и устанавливаем его как доступный в WP REST API. Это необходимый шаг, чтобы сделать метаданные поста доступными в редакторе Гутенберга. - Мы создаем файл Javascript и помещаем его в очередь специально для редактора (только).
- Внутри файла Javascript мы регистрируем плагин,
[registerPlugin](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-plugins/#registerPlugin)()сообщая ему об отображении нашего компонента. - Внутри этого компонента мы можем вывести все, что нам нужно. Мы можем использовать встроенные компоненты WordPress, чтобы легко отображать различные типы настроек. А с помощью пакета данных WordPress мы можем получать и обновлять мета-значения постов сразу же по мере их изменения.
Давайте приступим прямо к делу, начав с PHP-части; регистрация метаданных поста.
Регистрация метаданных поста
Для каждого мета сообщения, которое вы хотите добавить на боковую панель Gutenberg, вам нужно будет зарегистрироваться, используя [register_post_meta](https://developer.wordpress.org/reference/functions/register_post_meta/)(). Это необходимо, чтобы сделать их доступными через WP REST API (который использует Гутенберг) и, таким образом, доступными в нашем Javascript.
В файле вашей темы functions.phpили каком-либо другом активном PHP-файле добавьте функцию, привязанную к хуку ‘ init‘. Внутри функции вы повторяете a register_post_meta()для каждой пользовательской мета-записи, которую хотите добавить. Функция принимает три аргумента; Первый параметр — это тип сообщения, для которого вы хотите зарегистрировать метаданные (устанавливается как пустая строка для всех типов сообщений). Второй параметр — это имя мета-ключа для вашего мета-файла. И третье — это массив настроек. Именно здесь мы определяем, что эта мета должна быть доступна в WP REST API, установив для ‘ show_in_rest‘ значение true.
Например, предположим, что я хочу добавить переключатель включения/выключения и ввод текста на боковую панель редактора. Это означает, что я вызываю register_post_meta()логический и строковый типы значений соответственно. Я также хочу ограничить эти мета-сообщения только типом сообщения «сообщение». Это будет выглядеть примерно так:
add_action( 'init', function() {
register_post_meta( 'post', '_my_custom_bool', [
'show_in_rest' => true,
'single' => true,
'type' => 'boolean',
] );
register_post_meta( 'post', '_my_custom_text', [
'show_in_rest' => true,
'single' => true,
'type' => 'string',
] );
} );
Теперь у меня есть мета-ключ поста, _my_custom_boolи он _my_custom_textготов и доступен в Гутенберге. Я рекомендую вам переименовать их во что-то, что имеет для вас смысл.
Регистрация нашего плагина Javascript
На следующем шаге мы добавим файл Javascript и обязательно поставим его в очередь с помощью PHP.
Имейте в виду, что я пишу код Javascript с синтаксисом ES6. Это означает, что я настроил конфигурацию webpack/Babel для компиляции моего файла в отдельный читаемый файл Javascript для браузера.
У меня есть руководство о том, как это настроить, если вы не уверены, как это работает:
Нам нужно убедиться, что WordPress загружает наш скрипт в редактор. Мы делаем это, подключая функцию enqueue_block_editor_assetsи вызывая [wp_enqueue_script](https://developer.wordpress.org/reference/functions/wp_enqueue_script/)():
add_action( 'enqueue_block_editor_assets', function() {
wp_enqueue_script(
'awp-custom-meta-plugin',
get_template_directory_uri(). '/assets/js/gutenberg/plugin-awp-custom-postmeta.js',
[ 'wp-edit-post' ],
false,
false
);
} );
Я предполагаю, что вы знакомы с тем, как ставить сценарии в очередь, и можете заменить значения своими собственными. В качестве второго параметра я указываю путь к файлу сборки (не к исходному файлу). Чтобы наш скрипт не загружался слишком рано, я установил ‘ wp-edit-post‘ в качестве зависимости. Это пакет, который нам нужен для обработки метаданных постов.
Теперь давайте перейдем к части Javascript.
Сначала нам нужно вызвать [registerPlugin](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-plugins/#registerPlugin)()и передать наш компонент для рендеринга панели на боковой панели документа Gutenberg. Эта функция доступна в wp.pluginsпакете, поэтому я разбиваю ее вверху. Мне нравится содержать свои файлы в порядке, поэтому я создаю еще один файл; «awp-custom-postmeta-fields.js», чтобы содержать отображаемый компонент и импортировать его.
const { registerPlugin } = wp.plugins;
import AWP_Custom_Plugin from './awp-custom-postmeta-fields';
registerPlugin( 'my-custom-postmeta-plugin', {
render() {
return(<AWP_Custom_Plugin />);
}
} );
Пишем наш компонент
Давайте начнем создавать базовый компонент, который ничего не делает, кроме как просто сидит в правильном месте, так что мы сначала уберем его с пути. Чтобы отобразить компонент на боковой панели документа Gutenberg, мы используем [PluginDocumentSettingPanel](https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-document-setting-panel/)компонент. Мы можем установить такие атрибуты, как title, iconи className. И все, что внутри, будет отображаться на боковой панели документа. Пока я просто вывожу текст «Привет».
const { __ } = wp.i18n;
const { PluginDocumentSettingPanel } = wp.editPost;
const { PanelRow } = wp.components;
const AWP_Custom_Plugin =() => {
return(
<PluginDocumentSettingPanel title={ __( 'My Custom Post meta', 'txtdomain') } initialOpen="true">
<PanelRow>
Hello there.
</PanelRow>
</PluginDocumentSettingPanel>
);
}
export default AWP_Custom_Plugin;
С приведенным выше кодом (скомпилированным) мы получаем следующее:
Потрясающий. Однако мы хотим добавить некоторые входные данные. Но для того, чтобы связать эти входные данные с нашей пользовательской мета-метой поста, нам нужно скомпоновать наш компонент с компонентами более высокого порядка withSelect(чтобы получить мета-значения поста) и withDispatch(чтобы обновить мета-значения поста). Это может показаться немного сложным, если вы раньше не работали с компонентами более высокого порядка, но как только вы вникнете в это, это будет довольно просто.
Сначала нам нужно изменить наше exportутверждение. Вместо того, чтобы просто возвращать наш компонент в одиночку, нам нужно скомпоновать его с withSelectи withDispatch, оба в wp.dataпакете.
Внутри withSelect()у нас есть доступ к мощной select()функции. С помощью select()мы можем получить мета-значения текущего поста. Мы также можем получить текущий тип записи, если захотим. Как я упоминал ранее, при регистрации метаданных сообщений мы можем ограничить метаданные сообщений определенным типом сообщений. Если мы получаем тип сообщения текущего сообщения, мы можем в нашем компоненте убедиться, что наш код отображается только в том случае, если мы находимся на правильном типе сообщения. Подробнее об этом позже.
В withDispatch()мы можем определить функции, которые мы можем запускать в нашем компоненте. Мы создаем функцию, которая будет использоваться dispatch()для обновления метаданных поста.
Давайте изменим exportутверждение на это:
export default compose( [
withSelect( (select) => {
return {
postMeta: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
postType: select( 'core/editor' ).getCurrentPostType(),
};
} ),
withDispatch( (dispatch) => {
return {
setPostMeta( newMeta) {
dispatch( 'core/editor' ).editPost( { meta: newMeta } );
}
};
}) ] )( AWP_Custom_Plugin );
Нам также нужно деструктурировать их из следующих пакетов в верхней части файла:
const { compose } = wp.compose;
const { withSelect, withDispatch } = wp.data;
Благодаря этому наш AWP_Custom_Pluginкомпонент имеет доступ к трем новым реквизитам; postMetaкоторый содержит все мета-значения поста для текущего поста; postTypeкоторый содержит текущий тип сообщения; setPostMeta()и, наконец, созданная нами функция, withDispatch()которая будет обновлять метаданные поста.
Таким образом, в определении нашего компонента мы можем деструктурировать эти три новых реквизита;
const AWP_Custom_Plugin = ({ postType, postMeta, setPostMeta }) => {
...
И теперь мы можем добавить некоторые входные данные в наш рендеринг, убедившись, что они отображают текущее значение и обновляют метаданные поста в событии on change. Я зарегистрировал логическое значение и строку, поэтому в качестве примера я добавлю a ToggleControlдля переключателя и simple TextControlдля ввода текста.
Если вы не уверены во встроенных компонентах WordPress, у меня есть совершенно бесплатная электронная книга, в которой рассказывается почти о большинстве компонентов, доступных в Gutenberg, в том числе о том, какие реквизиты мы можем установить для каждого из них.
Вот пример того, как может выглядеть наш компонент:
const { ToggleControl, TextControl, PanelRow } = wp.components;
const AWP_Custom_Plugin = ({ postType, postMeta, setPostMeta }) => {
return(
<PluginDocumentSettingPanel title={ __( 'My Custom Post meta', 'txtdomain') } icon="edit" initialOpen="true">
<PanelRow>
<ToggleControl
label={ __( 'You can toggle me on or off', 'txtdomain') }
onChange={ (value) => setPostMeta( { _my_custom_bool: value }) }
checked={ postMeta._my_custom_bool }
/>
</PanelRow>
<PanelRow>
<TextControl
label={ __( 'Write some text, if you like', 'txtdomain') }
value={ postMeta._my_custom_text }
onChange={ (value) => setPostMeta( { _my_custom_text: value }) }
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
На линии #9-10и #16-17мы находим критические части. Мы устанавливаем текущее значение входов postMeta.<your meta key here>и в их событии onChange запускаем функцию setPostMeta( { <your meta key here>: ... } )для нового обновленного значения.
Наконец, несколько слов о том, как ограничить ваш компонент определенным типом сообщений. В нашем withSelect()мы передаем тип сообщения текущего сообщения в реквизите postType. Все, что нам нужно сделать в нашем компоненте, — это сравнить это значение с типом записи и вернуть null, если оно не совпадает:
const AWP_Custom_Plugin = ({ postType, postMeta, setPostMeta }) => {
if ('post' !== postType) return null; // Will only render component for post type 'post'
return(
...
Вот и все! Теперь наш код должен работать. Окончательный результат должен быть примерно таким:
Окончательный код
Регистрация метаданных публикации и постановка файла Javascript в очередь:
add_action( 'init', function() {
register_post_meta( 'post', '_my_custom_bool', [
'show_in_rest' => true,
'single' => true,
'type' => 'boolean',
] );
register_post_meta( 'post', '_my_custom_text', [
'show_in_rest' => true,
'single' => true,
'type' => 'string',
] );
} );
add_action( 'enqueue_block_editor_assets', function() {
wp_enqueue_script(
'awp-custom-meta-plugin',
get_template_directory_uri(). '/assets/js/gutenberg/plugin-awp-custom-postmeta.js',
[ 'wp-edit-post' ],
false,
false
);
} );
Два файла Javascript:
const { registerPlugin } = wp.plugins;
import AWP_Custom_Plugin from './awp-custom-postmeta-fields';
registerPlugin( 'my-custom-postmeta-plugin', {
render() {
return(<AWP_Custom_Plugin />);
}
} );
const { __ } = wp.i18n;
const { compose } = wp.compose;
const { withSelect, withDispatch } = wp.data;
const { PluginDocumentSettingPanel } = wp.editPost;
const { ToggleControl, TextControl, PanelRow } = wp.components;
const AWP_Custom_Plugin = ({ postType, postMeta, setPostMeta }) => {
if ('post' !== postType) return null; // Will only render component for post type 'post'
return(
<PluginDocumentSettingPanel title={ __( 'My Custom Post meta', 'txtdomain') } icon="edit" initialOpen="true">
<PanelRow>
<ToggleControl
label={ __( 'You can toggle me on or off', 'txtdomain') }
onChange={ (value) => setPostMeta( { _my_custom_bool: value }) }
checked={ postMeta._my_custom_bool }
/>
</PanelRow>
<PanelRow>
<TextControl
label={ __( 'Write some text, if you like', 'txtdomain') }
value={ postMeta._my_custom_text }
onChange={ (value) => setPostMeta( { _my_custom_text: value }) }
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
export default compose( [
withSelect( (select) => {
return {
postMeta: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
postType: select( 'core/editor' ).getCurrentPostType(),
};
} ),
withDispatch( (dispatch) => {
return {
setPostMeta( newMeta) {
dispatch( 'core/editor' ).editPost( { meta: newMeta } );
}
};
}) ] )( AWP_Custom_Plugin );


