Кастомная метабокс (SELECT) не сохраняется

Вопрос или проблема

Я пытаюсь создать метабокс с вариантами выбора для каждой страницы, к которой применен шаблон home-page-template.php. Эта функция работает корректно.

Я также хочу, чтобы он находился над редактором, под заголовком страницы, что раньше работало, но сейчас НЕТ. Я постоянно модифицировал код, пытаясь заставить его работать. Не уверен, что именно вызвало недоступность над редактором. Раньше это было ‘advanced’ вместо ‘up’, но сейчас ни один из них не работает.

Моя самая большая проблема в том, что при обновлении страницы выбор не сохраняется/не хранится. Я хочу получить ID страницы выбранного варианта и использовать его в переменной на page.php. ID страницы присваивается значению “value” для каждого варианта. Вот как я планирую получать ID страницы. Затем ID страницы нужно передать в переменную, которую я использую для получения значений дополнительных полей на page.php.

Вот код для functions.php:

/*   ** НАЧАЛО ** ДОБАВЛЯЕТ НОВЫЙ МЕТАБОКС НА СТРАНИЦЫ   */
// регистрируем метабокс
add_action( 'add_meta_boxes', 'my_custom_field_cityselect' );
add_action( 'load-page.php', 'my_custom_field_cityselect' );
add_action( 'load-page-new.php', 'my_custom_field_cityselect' );
function my_custom_field_cityselect() {
    add_meta_box(
        'my_select_meta_box_id',          // это HTML id бокса на экране редактирования
        'Выберите город для этой страницы',    // заголовок бокса
        'my_customfield_box_content',   // функция, которая будет вызываться для отображения флажков, смотрите функцию ниже
        'page',        // на каком экране редактирования должен появиться бокс
        'up',      // часть страницы, где должен появиться бокс
        'high'      // приоритет бокса
    );
}

// Перемещаем все метабоксы "up" выше стандартного редактора
function my_upper_meta_box() {     global $post, $wp_meta_boxes;
// Получаем глобальные переменные
do_meta_boxes( get_current_screen(), 'up', $post );
// Выводим метабоксы "up" 

} add_action( 'edit_form_after_title', 'my_upper_meta_box' );

// отображаем метабокс
function my_customfield_box_content($post) {
    // nonce поле для проверки безопасности, вы можете использовать одно и то же
    // nonce поле для всех ваших метабоксов одного плагина
    wp_nonce_field( basename( __FILE__ ), 'my_custom_field_select_nonce' );
    $meta_element_class = get_post_meta($post->ID, 'my_customfield_box_content', true);
    $args = array(
        'post_type' => 'page',
        'posts_per_page' => -1,
        'meta_query' => array(
            array(
                'key' => '_wp_page_template',
                'value' => 'page-home-template.php'
            )
        )
    );
    $the_pages = new WP_Query( $args );
    echo '<select style=\'width:300px;\' name=\'my_metabox_location\'>';
    echo '<option style=\'color:red\' value=\'0\'>Выберите подходящее местоположение</option>';
    if( $the_pages->have_posts() ){
        while( $the_pages->have_posts() ){
            $the_pages->the_post();
            $mymbpostid = get_the_ID();
            $mymbposttitle = str_replace("Снижение веса ","",get_the_title());
            $mymbposttitle = str_replace("Домашняя страница","(ДОМАШНЯЯ СТРАНИЦА) - НЕ ИСПОЛЬЗУЙТЕ ЭТУ ОПЦИЮ",get_the_title());
            echo '<option style=\'color:green\' value=\''. $mymbpostid .'\''. selected( $meta_element_class, '$mymbpostid' ) .'>'. $mymbposttitle .'</option>';
        }
    }
    wp_reset_postdata();

    echo '</select>';
}

// сохраняем данные из флажков
add_action( 'save_post', 'my_custom_field_data' );
function my_custom_field_data($post_id) {

    // проверка, является ли это автоматическим сохранением
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
        return;

    // проверка безопасности
    if ( !wp_verify_nonce( $_POST['mypluing_nonce'], plugin_basename( __FILE__ ) ) )
        return;

    // дополнительные проверки, если хотите, 
    // например, конкретный пользователь, роль или, возможно, тип поста в случае пользовательских типов постов

    // теперь сохраняем данные в пользовательских полях на основе выбранных флажков
    if ( isset( $_POST['my_metabox_location'] ) )
    {
        $meta_box_dropdown_value = $_POST["my_metabox_location"];
    }  
    update_post_meta( $post->ID, 'my_customfield_box_content', $_POST['meta_box_dropdown_value'] );
}
// Убираем метабокс с шаблона домашней страницы
add_action('admin_head','my_meta_init');
function my_meta_init(){
    $template_file = get_post_meta(get_the_ID(), '_wp_page_template', TRUE);

    if (($template_file == 'page-home-template.php')) {
        remove_meta_box('my_select_meta_box_id','page','advanced');    
    }
}

// Добавляем стили для метабокса
add_action('admin_head', 'custom_admin_meta_css');          
function custom_admin_meta_css() {
  echo '<style>#my_select_meta_box_id h2 {color:red}</style>';
}
/*   ** КОНЕЦ ** ДОБАВЛЯЕТ НОВЫЙ МЕТАБОКС НА СТРАНИЦЫ   */

И вот код для page.php (не уверен, что вторая строка что-то делает или вообще нужна):

<?php 
$loc_phone = get_field('location_phone_number', $mymbpostid);
$loc_info = get_post_meta( $post->ID,'my_custom_field_checkboxes',true );
echo '<h2>ID страницы - '. $loc_info .' | Телефон страницы - '. $loc_phone .'</h2>';
?>

Извиняюсь, если это горячий, запутанный беспорядок, так как я собрал кусочки из различных постов и склеил их вместе. Я чувствую, что близок, но просто не могу заставить это сохранить. Также не уверен, сохранится ли это уникально для каждой страницы, так как это необходимо.

ЛЮБАЯ ПОМОЩЬ БУДЕТ ОЧЕНЬ ОЦЕНЕНА. Примеры правильного кода – это лучшие ответы для меня, так как мои знания PHP и ядра WordPress опасно ограничены. Заранее спасибо!

Так что я придумал обходное решение, изуродовав это и добавив части из других решений, найденных в интернете. Это код, который я смог заставить работать корректно.
functions.php:

/*   ** НАЧАЛО ** ДОБАВЛЯЕТ НОВЫЙ МЕТАБОКС НА СТРАНИЦЫ   */
// регистрируем метабокс
add_action( 'add_meta_boxes', 'my_custom_field_cityselect' );
add_action( 'load-page.php', 'my_custom_field_cityselect' );
add_action( 'load-page-new.php', 'my_custom_field_cityselect' );
function my_custom_field_cityselect() {
    add_meta_box(
        'my_select_meta_box_id',          // это HTML id бокса на экране редактирования
        'Выберите город для этой страницы',    // заголовок бокса
        'my_customfield_box_content',   // функция, которая будет вызываться для отображения выбора, смотрите функцию ниже
        'page',        // на каком экране редактирования должен появиться бокс
        'normal',      // часть страницы, где должен появиться бокс
        'high'      // приоритет бокса
    );
}

// отображаем метабокс
function my_customfield_box_content($post) {
    // nonce поле для проверки безопасности, вы можете использовать одно и то же
    // nonce поле для всех ваших метабоксов одного плагина
    global $post;
    // сохраняем глобальный объект поста, чтобы он не путался с вариантами
    $post_old = $post;

    $custom = get_post_custom($post->ID);
    if (isset($custom["meta_element_class"][0])) {
    $meta_element_class = $custom["meta_element_class"][0];
    } else {
    $meta_element_class="0";
    }
    $args = array(
        'post_type' => 'page',
        'posts_per_page' => -1,
        'meta_query' => array(
            array(
                'key' => '_wp_page_template',
                'value' => 'page-home-template.php'
            )
        )
    );
    $posts = get_posts($args);
    echo '<select style=\'width:300px;\' name=\'my_metabox_location\' id=\'my_metabox_location\'>';
    echo '<option style=\'color:red\' value=\'0\''. selected( $meta_element_class, '0' ) .'>Выберите подходящее местоположение</option>';
    foreach( $posts as $post ) : setup_postdata($post);
        $mymbpostid = $post->ID;
        $mymbposttitle = str_replace("Снижение веса ","",get_the_title());
        $mymbposttitle = str_replace("Домашняя страница","(ДОМАШНЯЯ СТРАНИЦА) - НЕ ИСПОЛЬЗУЙТЕ ЭТУ ОПЦИЮ",get_the_title());
        echo '<option style=\'color:green\' value=\''. $mymbpostid .'\''. selected( $meta_element_class, $mymbpostid ) .'>'. $mymbposttitle .'</option>';
    endforeach;

    echo '</select>';
    // восстанавливаем глобальный объект поста
    $post = $post_old;
    setup_postdata( $post );
}

// сохраняем данные из выбора
add_action( 'save_post', 'my_custom_field_data' );
function my_custom_field_data() {
    global $post;
    // проверка, является ли это автоматическим сохранением
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
        return;

    // дополнительные проверки, если хотите, 
    // например, конкретный пользователь, роль или, возможно, тип поста в случае пользовательских типов постов

    // теперь сохраняем данные в пользовательских полях на основе выбранной опции
    if ( isset( $_POST['my_metabox_location'] ) )
    {
        update_post_meta( $post->ID, 'meta_element_class', $_POST['my_metabox_location'] );
    }
}
// Убираем метабокс с шаблона домашней страницы
add_action('admin_head','my_meta_init');
function my_meta_init(){
    $template_file = get_post_meta(get_the_ID(), '_wp_page_template', TRUE);

    if (($template_file == 'page-home-template.php')) {
        remove_meta_box('my_select_meta_box_id','page','advanced');    
    }
}

// Добавляем стили для метабокса
add_action('admin_head', 'custom_admin_meta_css');          
function custom_admin_meta_css() {
  echo '<style>#my_select_meta_box_id h2 {color:red}</style>';
}
/*   ** КОНЕЦ ** ДОБАВЛЯЕТ НОВЫЙ МЕТАБОКС НА СТРАНИЦЫ   */

И вот этот код в page.php:

<?php $meta_element_class = get_post_meta($post->ID, 'meta_element_class', true); ?>
<?php $loc_phone = get_field('location_phone_number', $meta_element_class); ?>
<?php echo '<h2>ID страницы - '. $meta_element_class .' | Телефон страницы - '. $loc_phone .'</h2>'; ?>

С WordPress 5.0.3 и плагином Classic Editor установленным, я все еще не могу заставить метабокс отображаться над редактором контента. Если кто-то знает, как это сделать, была бы очень признателен за помощь.

Ответ или решение

Проблема с сохранением пользовательского метаполя (SELECT) в WordPress

Создание пользовательских метаполей в WordPress может быть не таким простым, как кажется на первый взгляд. Если вы столкнулись с проблемой, когда ваше метаполе с выпадающим списком (SELECT) не сохраняет данные, вы не одиноки. В этой статье мы разберём вашу ситуацию детально и предложим рекомендации по её решению.

1. Проверка кода для метаполя

Ваш первоначальный код использует несколько стандартных функций WordPress для создания метабоксов. Вот основные моменты, на которые стоит обратить внимание:

  1. Проверка nonce: Вы правильно используете wp_nonce_field для проверки безопасности, но в коде сохранения данных нехватало проверки корректности nonce. В конце функции сохранения данных, убедитесь, что вы заменили ключ mypluing_nonce на правильный, который вы используете (в данном случае my_custom_field_select_nonce).
if (!wp_verify_nonce($_POST['my_custom_field_select_nonce'], basename(__FILE__))) {
    return;
}
  1. Сохранение данных: Ваша функция my_custom_field_data должна корректно сохранять значение метаполя. Вместо использования строки $_POST['meta_box_dropdown_value'], следует использовать $_POST['my_metabox_location'], поскольку именно этот ключ используется в вашей функции отображения метабокса.
if (isset($_POST['my_metabox_location'])) {
    update_post_meta($post->ID, 'my_customfield_box_content', $_POST['my_metabox_location']);
}

2. Перемещение метабокса

Чтобы разместить метабокс выше редактора, вы используете add_action('edit_form_after_title', 'my_upper_meta_box'), что является правильным подходом. Убедитесь, что ваши функции правильно привязаны к нужным хукам и работающими. Учтите, что при перемещении метабокса может потребоваться использовать хук с приоритетом, чтобы убедиться, что вы вызываете его в правильное время.

Пример кода:

function my_upper_meta_box() {
    global $post, $wp_meta_boxes;
    do_meta_boxes(get_current_screen(), 'normal', $post);
}
add_action('edit_form_after_title', 'my_upper_meta_box');

3. Вызов данных в page.php

Ваш код для получения данных в файле page.php выглядит неплохо. Просто убедитесь, что вы используете правильные переменные:

$meta_element_class = get_post_meta($post->ID, 'my_customfield_box_content', true);
$loc_phone = get_field('location_phone_number', $meta_element_class);
echo '<h2>Page ID - '. esc_html($meta_element_class) .' | Page Phone - '. esc_html($loc_phone) .'</h2>';

Использование esc_html() — хорошая практика для обеспечения безопасности при выводе данных.

4. Окончательные рекомендации

  1. Проверка конфликтов плагинов: Убедитесь, что другие плагины не конфликтуют с вашим кодом. Попробуйте отключить все другие плагины и проверить, сохраняется ли ваше метаполе.

  2. Отладка: Если проблема сохраняется, добавьте логи для проверки значений переменных в критических участках кода. Это может помочь выявить, сохраняет ли ваш код данные или же происходит сбой на каком-то этапе.

  3. Тестирование в новом окружении: Создайте тестовый сайт на локальной машине или на другом сервере или установите другую тему, чтобы убедиться, что ваша проблема не связана с конкретной конфигурацией сайта.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...