WordPress. Пользовательские мета-боксы

Дополнительные материалы
https://misha.agency/course/wordpress-custom-fields
https://misha.agency/wordpress/meta-boxes.html

Что такое метабокс?

Когда пользователь редактирует сообщение, экран редактирования состоит из нескольких полей по умолчанию: «Редактор», «Публикация», «Категории», «Теги» и т. д. Эти поля являются мета-полями. Плагины могут добавлять пользовательские мета-поля на экран редактирования любого типа сообщений.

Содержимое пользовательских мета-полей обычно представляет собой элементы HTML-формы, в которые пользователь вводит данные, относящиеся к назначению плагина, но содержимое может быть практически любым HTML-кодом, который вы пожелаете.

Зачем использовать метабоксы?

Метабоксы — это удобные, гибкие, модульные элементы экрана редактирования, которые можно использовать для сбора информации, связанной с редактируемым сообщением. Ваше пользовательское мета-окно будет на том же экране, что и вся остальная информация, связанная с публикацией; поэтому устанавливается четкая связь.

Метабоксы легко скрыть от пользователей, которым не нужно их видеть, и показать тем, кому это нужно. Метабоксы могут быть расположены пользователем на экране редактирования. Пользователи могут расположить экран редактирования так, как им удобно, предоставляя пользователям контроль над своей средой редактирования.

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

Добавление мета-боксов

Чтобы создать метабокс, используйте функцию add_meta_box() и подключите ее выполнение к add_meta_boxes хуку действия.

В следующем примере показано добавление метаполя на экран редактирования post и на экран редактирования wporg_cpt.

function wporg_add_custom_box() {
	$screens = [ 'post', 'wporg_cpt' ];
	foreach ( $screens as $screen ) {
		add_meta_box(
			'wporg_box_id',                 // Unique ID
			'Custom Meta Box Title',      // Box title
			'wporg_custom_box_html',  // Content callback, must be of type callable
			$screen                            // Post type
		);
	}
}
add_action( 'add_meta_boxes', 'wporg_add_custom_box' );

Функция wporg_custom_box_html будет содержать HTML для мета-поля.

В следующем примере показано добавление элементов формы, меток и других элементов HTML.

function wporg_custom_box_html( $post ) {
	?>
	<label for="wporg_field">Description for this field</label>
	<select name="wporg_field" id="wporg_field" class="postbox">
		<option value="">Select something...</option>
		<option value="something">Something</option>
		<option value="else">Else</option>
	</select>
	<?php
}
Примечание:Обратите внимание, что в мета-полях нет кнопок отправки. Мета-поле HTML включено в теги формы экрана редактирования, все данные публикации, включая значения мета-поля, передаются через него, POSTкогда пользователь нажимает кнопки «Опубликовать» или «Обновить».

Показанный здесь пример содержит только одно поле формы — раскрывающийся список. Вы можете создать столько, сколько необходимо в любом конкретном метабоксе. Если у вас есть много полей для отображения, рассмотрите возможность использования нескольких мета-полей, группируя похожие поля вместе в каждом мета-поле. Это помогает сделать страницу более организованной и визуально привлекательной.

Получение значений

Чтобы получить сохраненные пользовательские данные и использовать их, вам нужно получить их оттуда, где вы их изначально сохранили. Если он был сохранен в postmetaтаблице, вы можете получить данные с помощью get_post_meta() .

В следующем примере улучшены предыдущие элементы формы с предварительно заполненными данными на основе сохраненных значений метаполя. В следующем разделе вы узнаете, как сохранить значения мета-поля.

function wporg_custom_box_html( $post ) {
	$value = get_post_meta( $post->ID, '_wporg_meta_key', true );
	?>
	<label for="wporg_field">Description for this field</label>
	<select name="wporg_field" id="wporg_field" class="postbox">
		<option value="">Select something...</option>
		<option value="something" <?php selected( $value, 'something' ); ?>>Something</option>
		<option value="else" <?php selected( $value, 'else' ); ?>>Else</option>
	</select>
	<?php
}

Сохранение значений

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

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

В следующем примере wporg_field значение поля будет сохранено в _wporg_meta_key скрытом мета-ключе.

function wporg_save_postdata( $post_id ) {
	if ( array_key_exists( 'wporg_field', $_POST ) ) {
		update_post_meta(
			$post_id,
			'_wporg_meta_key',
			$_POST['wporg_field']
		);
	}
}
add_action( 'save_post', 'wporg_save_postdata' );

В производственном коде не забывайте соблюдать меры безопасности, указанные в информационном окне!

За кулисами

Обычно вам не нужно беспокоиться о том, что происходит за кулисами. Этот раздел был добавлен для полноты.

Когда экран редактирования сообщения хочет отобразить все добавленные к нему метабоксы, он вызывает функцию do_meta_boxes() . Эта функция перебирает все метаполя и вызывает callbackсвязанные с каждым из них.
Между каждым вызовом добавляется промежуточная разметка (например, div, заголовки и т. д.).

Удаление мета-боксов

Чтобы удалить существующий метабокс с экрана редактирования, используйте функцию remove_meta_box() . Передаваемые параметры должны точно совпадать с теми, которые использовались для добавления метабокса с помощью add_meta_box() .

Чтобы удалить мета-поля по умолчанию, проверьте исходный код на наличие используемых параметров. Вызовы add_meta_box() по умолчанию выполняются из файлов wp-includes/edit-form-advanced.php.

Варианты реализации

До сих пор мы использовали процедурную технику реализации метабоксов. Многие разработчики плагинов считают необходимым реализовать метабоксы, используя различные другие методы.

ООП

Добавлять метабоксы с помощью ООП легко и избавляет вас от необходимости беспокоиться о коллизиях имен в глобальном пространстве имен.
Чтобы сэкономить память и упростить реализацию, в следующем примере используется абстрактный класс со статическими методами.

abstract class WPOrg_Meta_Box {


	/**
	 * Set up and add the meta box.
	 */
	public static function add() {
		$screens = [ 'post', 'wporg_cpt' ];
		foreach ( $screens as $screen ) {
			add_meta_box(
				'wporg_box_id',          // Unique ID
				'Custom Meta Box Title', // Box title
				[ self::class, 'html' ],   // Content callback, must be of type callable
				$screen                  // Post type
			);
		}
	}


	/**
	 * Save the meta box selections.
	 *
	 * @param int $post_id  The post ID.
	 */
	public static function save( int $post_id ) {
		if ( array_key_exists( 'wporg_field', $_POST ) ) {
			update_post_meta(
				$post_id,
				'_wporg_meta_key',
				$_POST['wporg_field']
			);
		}
	}


	/**
	 * Display the meta box HTML to the user.
	 *
	 * @param WP_Post $post   Post object.
	 */
	public static function html( $post ) {
		$value = get_post_meta( $post->ID, '_wporg_meta_key', true );
		?>
		<label for="wporg_field">Description for this field</label>
		<select name="wporg_field" id="wporg_field" class="postbox">
			<option value="">Select something...</option>
			<option value="something" <?php selected( $value, 'something' ); ?>>Something</option>
			<option value="else" <?php selected( $value, 'else' ); ?>>Else</option>
		</select>
		<?php
	}
}

add_action( 'add_meta_boxes', [ 'WPOrg_Meta_Box', 'add' ] );
add_action( 'save_post', [ 'WPOrg_Meta_Box', 'save' ] );

АЯКС

Поскольку HTML-элементы мета-поля находятся внутри formтегов экрана редактирования, поведением по умолчанию является синтаксический анализ значений мета-поля из суперглобального $_POSTполя после того, как пользователь отправил страницу .

Вы можете улучшить работу по умолчанию с помощью AJAX; это позволяет выполнять действия на основе пользовательского ввода и поведения; независимо от того, отправили ли они страницу.

Определить триггер

Во-первых, вы должны определить триггер, это может быть переход по ссылке, изменение значения или любое другое событие JavaScript.

В приведенном ниже примере мы определим changeнаш триггер для выполнения запроса AJAX.

/*jslint browser: true, plusplus: true */
(function ($, window, document) {
    'use strict';
    // execute when the DOM is ready
    $(document).ready(function () {
        // js 'change' event triggered on the wporg_field form field
        $('#wporg_field').on('change', function () {
            // our code
        });
    });
}(jQuery, window, document));

Код на стороне клиента

Затем нам нужно определить, что мы хотим, чтобы триггер делал, другими словами, нам нужно написать код на стороне клиента.

В приведенном ниже примере мы сделаем POSTзапрос, ответ будет либо успешным, либо неудачным, это укажет, что значение wporg_fieldдействительно.

/*jslint browser: true, plusplus: true */
(function ($, window, document) {
    'use strict';
    // execute when the DOM is ready
    $(document).ready(function () {
        // js 'change' event triggered on the wporg_field form field
        $('#wporg_field').on('change', function () {
            // jQuery post method, a shorthand for $.ajax with POST
            $.post(wporg_meta_box_obj.url,                        // or ajaxurl
                   {
                       action: 'wporg_ajax_change',                // POST data, action
                       wporg_field_value: $('#wporg_field').val(), // POST data, wporg_field_value
                       post_ID: jQuery('#post_ID').val()           // The ID of the post currently being edited
                   }, function (data) {
                        // handle response data
                        if (data === 'success') {
                            // perform our success logic
                        } else if (data === 'failure') {
                            // perform our failure logic
                        } else {
                            // do nothing
                        }
                    }
            );
        });
    });
}(jQuery, window, document));

Мы динамически взяли URL-адрес файла WordPress AJAX из wporg_meta_box_objпользовательского объекта JavaScript, который мы создадим на следующем шаге.

Примечание:Если для вашего метабокса требуется только URL-адрес файла WordPress AJAX; вместо создания нового пользовательского объекта JavaScript вы можете использовать ajaxurlпредопределенную переменную JavaScript.
Доступно только в Администрации WordPress. Перед выполнением какой-либо логики убедитесь, что он не пуст.

Поставить в очередь клиентский код

Следующий шаг — поместить наш код в файл сценария и поставить его в очередь на наших экранах редактирования.

В приведенном ниже примере мы добавим функциональность AJAX на экраны редактирования следующих типов записей: post, wporg_cpt.

Файл скрипта будет находиться в /plugin-name/admin/meta-boxes/js/admin.jsосновной
plugin-nameпапке плагина,
/plugin-name/plugin.phpфайле, вызывающем функцию.

function wporg_meta_box_scripts()
{
    // get current admin screen, or null
    $screen = get_current_screen();
    // verify admin screen object
    if (is_object($screen)) {
        // enqueue only for specific post types
        if (in_array($screen->post_type, ['post', 'wporg_cpt'])) {
            // enqueue script
            wp_enqueue_script('wporg_meta_box_script', plugin_dir_url(__FILE__) . 'admin/meta-boxes/js/admin.js', ['jquery']);
            // localize script, create a custom js object
            wp_localize_script(
                'wporg_meta_box_script',
                'wporg_meta_box_obj',
                [
                    'url' => admin_url('admin-ajax.php'),
                ]
            );
        }
    }
}
add_action('admin_enqueue_scripts', 'wporg_meta_box_scripts');

Код на стороне сервера

Последний шаг — написать код на стороне сервера, который будет обрабатывать запрос.

// The piece after `wp_ajax_`  matches the action argument being sent in the POST request.
add_action( 'wp_ajax_wporg_ajax_change', 'my_ajax_handler' );
 
/**
 * Handles my AJAX request.
 */
function my_ajax_handler() {
    // Handle the ajax request here
    if ( array_key_exists( 'wporg_field_value', $_POST ) ) {
        $post_id = (int) $_POST['post_ID'];
        if ( current_user_can( 'edit_post', $post_id ) ) {
            update_post_meta(
                $post_id,
                '_wporg_meta_key',
                $_POST['wporg_field_value']
            );
        }
    }
 
    wp_die(); // All ajax handlers die when finished
}

И последнее напоминание: в коде, показанном на этой странице, отсутствуют важные операции, обеспечивающие безопасность. Убедитесь, что ваш производственный код включает такие операции.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *