Вопрос или проблема
Какова лучшая практика для этого в Gutenberg/JavaScript:
update_post_meta( $page_id, '_custom_post_meta', 'Некоторые данные для сохранения' );
- Мне нужно сделать это из боковой панели
- Пользовательский мета-поле зарегистрировано, и я могу обновить его для редактируемого поста
- Мне нужно сделать это для другого поста, а не для редактируемого в данный момент
Вот пример использования:
const UpdateMeta = () => {
const { editPost } = useDispatch( 'core/editor' );
const onChange = ( value ) => {
editPost( { // Я обновляю здесь редактируемый пост, и это нормально
meta: { _custom_meta : JSON.stringify( value ) },
} );
// Но я хотел бы изменить некоторые метаданные другого поста, выбранного по его ID
};
return (
<FormTokenField
value={ selectedContinents }
suggestions={ suggestionsList }
__experimentalShowHowTo={false}
onChange={ onChange }
displayTransform={ prepare }
/>
);
}
const Component = () => (
<PluginDocumentSettingPanel
title={ 'Моя боковая панель' }>
<UpdateMeta/>
</PluginDocumentSettingPanel>
);
registerPlugin( 'my-plugin-name', {
icon: '',
render: Component,
} );
Я исключил не относящиеся к делу части кода.
Обновление:
Я делюсь полным кодом здесь (код в разработке, пожалуйста, игнорируйте возможные ошибки и недостатки):
const { registerPlugin } = wp.plugins;
const { FormTokenField } = wp.components;
const { PluginDocumentSettingPanel } = wp.editPost;
const { useSelect, useDispatch } = wp.data;
const { useState } = wp.element;
let targetType="";
const RelatedDifferentTypePosts = () => {
const postType = wp.data.select( 'core/editor' ).getCurrentPostType();
switch ( postType ) {
case 'display':
targetType="event";
break;
case 'event':
targetType="display";
break;
}
const postMetaField = `_assigned_${ targetType }s`;
const isLoading = useSelect( ( select ) => {
return select( 'core/data' ).isResolving( 'core', 'getEntityRecords', [
'postType', targetType
] );
} );
const assignedPosts = useSelect(
( select ) => select( 'core/editor' ).getEditedPostAttribute( 'meta' )[postMetaField], []
);
const targetPostsRaw = useSelect(
( select ) => select( 'core' ).getEntityRecords( 'postType', targetType ), []
);
let valueTitlePair = [];
if ( targetPostsRaw ) {
valueTitlePair = targetPostsRaw.map( ( postItem ) => {
const tempObj = {};
tempObj.id = postItem.id;
tempObj.slug = postItem.slug;
return tempObj;
} );
}
const slugs = assignedPosts ? Array.from( JSON.parse( assignedPosts ), ( item ) => { return item.slug; } ) : [];
const [ selectedPosts, setSelectedPosts ] = useState( slugs );
let suggestionsList;
if ( targetPostsRaw ) {
suggestionsList = Array.from( targetPostsRaw, ( postItem ) => {
return postItem.slug;
} );
}
const { editPost } = useDispatch( 'core/editor' );
const onChange = ( value ) => {
/* Предотвратить ввод несуществующих событий */
value = value.filter( ( entry ) => suggestionsList.includes( entry ) );
setSelectedPosts( value );
value = valueTitlePair.filter( pair => value.includes( pair.slug ) );
editPost( {
meta: { [ postMetaField ] : JSON.stringify( value ) },
} );
};
const prepare = ( token ) => {
return token.replaceAll( '-', ' ' ).replace( /(^\w|\s\w)/g, m => m.toUpperCase() );
};
if ( isLoading ) {
return <h3>Загрузка...</h3>;
}
return (
<FormTokenField
value={ selectedPosts }
suggestions={ suggestionsList }
__experimentalShowHowTo={false}
onChange={ onChange }
displayTransform={ prepare }
/>
);
};
/**
* Компонент
*/
const Component = () => (
<PluginDocumentSettingPanel
title={ `Связанные ${ targetType.charAt( 0 ).toUpperCase() + targetType.slice( 1 ) }` }>
<RelatedDifferentTypePosts/>
</PluginDocumentSettingPanel>
);
registerPlugin( 'related-posts-of-different-type', {
icon: '',
render: Component,
} );
Я смог сделать это, используя Backbone JavaScript Client, предоставленный в составе основных скриптов wp-api
.
Вы можете получить пост, обновить его мета-данные и сохранить его. Убедитесь, что вы wp_enqueue_script( 'wp-api' )
или добавили его в зависимости своего скрипта, чтобы API был доступен в JavaScript по адресу wp.api
.
Пример:
const post = new wp.api.models.Post( { id: 123 } );
post.fetch().done( () => {
post.setMeta( 'your_meta_field', 'your_meta_string_content' );
post.save().done( () => {
// Любые действия, которые нужно выполнить после сохранения мета-данных.
} );
} );
Методы Backbone Client не имеют хорошей документации на данный момент, но вы можете просмотреть их в исходном коде. Например, setMeta()
можно найти здесь: https://github.com/WordPress/WordPress/blob/master/wp-includes/js/wp-api.js#L543-L553
Будьте осторожны, поскольку API возвращает промисы для большинства методов; легко допустить ошибку (например, попытаться установить мета-данные поста до того, как пост был загружен, что не даст никаких результатов).
Также имейте в виду, что REST API имеет конечные точки для каждого типа поста, поэтому вам нужно будет использовать разные модели для каждого. Например, wp.api.models.Post
, wp.api.models.Page
, wp.api.models.YourCustomPostTypes
и т.д. Возможно, вам придется сохранить эту информацию вместе с ID, чтобы знать, какую конечную точку использовать.
Ответ или решение
Чтобы редактировать метаданные поста по его ID в редакторе Gutenberg, необходимо прибегнуть к REST API WordPress и использовать объекты, предоставляемые Backbone.js. Основная идея заключается в том, чтобы сначала запросить нужный пост, обновить его метаданные и затем сохранить изменения. Ниже представлена пошаговая инструкция и пример кода для решения вашей задачи.
Шаги для редактирования метаданных поста по ID
-
Подготовка окружения:
Убедитесь, что у вас подключён скриптwp-api
, иначе вы не сможете работать с REST API. Если вы создаёте свой скрипт, добавьте его зависимости в функцииwp_enqueue_script
.function my_enqueue_scripts() { wp_enqueue_script( 'wp-api' ); } add_action( 'admin_enqueue_scripts', 'my_enqueue_scripts' );
-
Создание функционала для обновления метаданных:
Используйте методfetch()
для получения объекта поста иsetMeta()
для установки нужных метаданных. Как только метаданные установлены, их нужно сохранить с помощью методаsave()
.
Пример кода
Ниже приведён пример компонента, который позволяет редактировать метаданные другого поста:
const { registerPlugin } = wp.plugins;
const { PluginDocumentSettingPanel } = wp.editPost;
const { FormTokenField } = wp.components;
const { useDispatch } = wp.data;
const { useState, useEffect } = wp.element;
const UpdatePostMeta = ({ targetPostId }) => {
const [metaValue, setMetaValue] = useState('');
const updateMeta = (value) => {
const post = new wp.api.models.Post({ id: targetPostId });
post.fetch().done(() => {
post.setMeta('_custom_post_meta', value);
post.save().done(() => {
console.log('Метаданные успешно обновлены!');
}).fail((error) => {
console.error('Ошибка при сохранении метаданных:', error);
});
}).fail((error) => {
console.error('Ошибка при получении поста:', error);
});
};
return (
<FormTokenField
value={metaValue}
suggestions={[]}
onChange={(value) => {
setMetaValue(value);
updateMeta(value);
}}
/>
);
};
const MySidebarComponent = () => {
// Здесь определите ID целевого поста, метаданные которого вы хотите обновить
const targetPostId = 123; // Замените на нужный ID поста
return (
<PluginDocumentSettingPanel
title="Обновить метаданные"
initialOpen={true}
>
<UpdatePostMeta targetPostId={targetPostId} />
</PluginDocumentSettingPanel>
);
};
registerPlugin('my-post-meta-plugin', {
render: MySidebarComponent,
});
Пояснение:
-
Компонент
UpdatePostMeta
:- Мы создаём состояние
metaValue
для хранения значения, которое мы хотим сохранить в метаданные. - В функции
updateMeta
происходит запрос поста с помощьюfetch()
, установка метаданных с помощьюsetMeta()
и сохранение с помощьюsave()
.
- Мы создаём состояние
-
Компонент
MySidebarComponent
:- Содержит панель
PluginDocumentSettingPanel
, где и будет отображаться поле для ввода метаданных. - Убедитесь, что вы передаёте правильный ID поста, который нужно обновить.
- Содержит панель
Заключение
Пользуясь описанными шагами, вы сможете редактировать метаданные любого поста в WordPress через интерфейс Gutenberg, используя JavaScript и REST API. Убедитесь, что у вас есть все необходимые разрешения для работы с постами через API, и тестируйте ваш код на локальном окружении перед тем, как применять его на живом сайте.