Вопрос или проблема
У меня проблема с моим пользовательским блоком Gutenberg. Сам по себе он работает идеально на каждой странице или посте. Но, когда я хочу добавить этот блок, который настроен как динамический, к пользовательскому типу записи, появляется сообщение “Этот блок столкнулся с ошибкой и не может быть предпросмотрен.”. В чем может быть проблема? Код приведен здесь. Заранее спасибо.
plugin.php – определение пользовательского блока Gutenberg
function movieFavQuote() {
wp_enqueue_script(
'favquote-handler',
plugin_dir_url(__FILE__) . 'quote-block.js',
array('wp-blocks', 'wp-i18n', 'wp-editor'),
true
);
}
add_action('enqueue_block_editor_assets', 'movieFavQuote');
function favQuoteMeta() {
register_meta('post', 'content', array('show_in_rest' => true, 'type' => 'string', 'single' => true));
}
add_action('init', 'favQuoteMeta');
quote-block.js – определение пользовательского блока Gutenberg
wp.blocks.registerBlockType('pavle/movie-quote', {
title: 'Любимая цитата из фильма',
icon: "smiley",
category: "common",
attributes: {
content: {type: 'string', source: 'meta', meta: 'content'}
},
edit: function(props) {
function updateContent(event) {
props.setAttributes({content: event.target.value})
}
return wp.element.createElement(
"div",
null,
wp.element.createElement("h3", null, " Любимая цитата из фильма: "),
wp.element.createElement("input", {
type: "text",
value: props.attributes.content,
onChange: updateContent
})
);
},
save: function(props) {
return wp.element.createElement("h2", null, " Любимая цитата из фильма:", props.attributes.content);
}
})
movies.php – определение пользовательского типа записи
<?php
function movie_cpt() {
$labels = array(
'name' => _x( 'Фильмы', 'Post Type General Name', 'text_domain' ),
'singular_name' => _x( 'Фильм', 'Post Type Singular Name', 'text_domain' ),
'menu_name' => __( 'Фильмы', 'text_domain' ),
'name_admin_bar' => __( 'Фильмы', 'text_domain' ),
'archives' => __( 'Архив фильмов', 'text_domain' ),
'attributes' => __( 'Атрибуты элемента', 'text_domain' ),
'parent_item_colon' => __( 'Родительский элемент:', 'text_domain' ),
'all_items' => __( 'Все фильмы', 'text_domain' ),
'add_new_item' => __( 'Добавить новый фильм', 'text_domain' ),
'add_new' => __( 'Добавить новый фильм', 'text_domain' ),
'new_item' => __( 'Новый фильм', 'text_domain' ),
'edit_item' => __( 'Редактировать фильм', 'text_domain' ),
'update_item' => __( 'Обновить фильм', 'text_domain' ),
'view_item' => __( 'Просмотреть фильм', 'text_domain' ),
'view_items' => __( 'Просмотреть фильм', 'text_domain' ),
'search_items' => __( 'Поиск фильмов', 'text_domain' ),
'not_found' => __( 'Фильм не найден', 'text_domain' ),
'not_found_in_trash' => __( 'Фильм не найден в корзине', 'text_domain' ),
'featured_image' => __( 'Изображение записи', 'text_domain' ),
'set_featured_image' => __( 'Установить изображение записи', 'text_domain' ),
'remove_featured_image' => __( 'Удалить изображение записи', 'text_domain' ),
'use_featured_image' => __( 'Использовать как изображение записи', 'text_domain' ),
'insert_into_item' => __( 'Вставить в элемент', 'text_domain' ),
'uploaded_to_this_item' => __( 'Загружено в этот элемент', 'text_domain' ),
'items_list' => __( 'Список фильмов', 'text_domain' ),
'items_list_navigation' => __( 'Навигация по списку элементов', 'text_domain' ),
'filter_items_list' => __( 'Фильтр списка элементов', 'text_domain' ),
);
$args = array(
'label' => __( 'Фильм', 'text_domain' ),
'description' => __( 'Описание типа записи', 'text_domain' ),
'labels' => $labels,
'supports' => array( 'title', 'editor'),
'taxonomies' => array( 'category', 'post_tag' ),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 5,
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'page',
'show_in_rest' => true,
'register_meta_box_cb' => 'movie_meta_box'
);
register_post_type( 'movie', $args );
}
add_action( 'init', 'movie_cpt');
function movie_meta_box() {
add_meta_box(
'movie-title',
__('Название фильма', 'sitepoint'),
'movie_title_meta_box_callback',
);
}
add_action('add_meta_boxes_movie', 'movie_meta_box');
function movie_title_meta_box_callback($post) {
wp_nonce_field('movie_title_nonce', 'movie_title_nonce');
$value = get_post_meta($post->ID, '_movie_title', true);
echo '<textarea style = "width:100%" id="movie_title" name="movie_title">' . esc_attr( $value ) . '</textarea>';
}
function save_movie_title_meta_box_data($post_id) {
if (!isset($_POST['movie_title_nonce'])) {
return;
}
if(!wp_verify_nonce( $_POST['movie_title_nonce'], 'movie_title_nonce' )) {
return;
}
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if(isset($_POST['post_type']) && 'page' == $_POST['post_type']) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return;
}
}
else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
}
if(!isset($_POST['movie_title'])) {
return;
}
$my_data = sanitize_text_field( $_POST['movie_title'] );
update_post_meta( $post_id, '_movie_title', $my_data );
}
add_action('save_post', 'save_movie_title_meta_box_data');
Попробуйте добавить custom-fields в массив поддержки;
'supports' => [
'title',
'editor',
'thumbnail',
'custom-fields'
],
Ответ или решение
Ошибка с блоком Gutenberg, о которой идет речь, чаще всего связана с тем, что блок или не может получить нужные данные из мета-полей, или просто неправильно зарегистрирован для работы с определённым типом контента. Давайте проанализируем несколько возможных причин этого и предложим решения.
Теория
Одной из основных причин проблемы может быть несоответствие в настройках регистрации мета-полей и способов их возращения в REST API. В вашем коде используется функция register_meta
для определения мета-поля ‘content’. Однако, если этот мета-подключенный блок должен работать с конкретным типом записи, то нужно убедиться, что:
- Мета-поля зарегистрированы корректно и связаны с нужным типом записи.
- Блок зарегистрирован в конфигурации REST API.
Пример
Отрывок вашего кода, регистрирующий мета-полe, выглядит следующим образом:
register_meta('post', 'content', array('show_in_rest' => true, 'type' => 'string', 'single' => true));
В этой строке функция связывает мета-поле ‘content’ с типом постов ‘post’. Но учитывая, что ваш блок используется в кастомном пост-типе ‘movie’, это создает конфликт. Вы дополнительно можете добавить проверку на наличие этого мета-поля для вашего кастомного типа записи.
Также, в movies.php
у вас не добавлены ‘custom-fields’ в параметр ‘supports’. При добавлении, ваш код может менять настройки и доступа к мета-полям, связанным с пост типом.
Применение
-
Обновите регистрацию мета-полей, чтобы она была более специфичной для вашего кастомного пост-типа:
function favQuoteMeta() { register_meta('movie', 'content', array('show_in_rest' => true, 'type' => 'string', 'single' => true)) } add_action('init', 'favQuoteMeta');
-
Убедитесь, что в конфигурации кастомного пост-типа включено ‘supports’ для поддержки ‘custom-fields’:
$args = array( 'supports' => array('title', 'editor', 'thumbnail', 'custom-fields') // Остальные параметры );
Эти изменения должны обеспечить корректную работу вашего динамического блока в рамках настроенного типа постов. За счет этого ошибки в отображении блока Gutenberg при использовании в кастомных записях ‘movie’ быть не должно. Будьте внимательны к изменению структуры доступа ваших данных и их синхронизации с REST API.