Дополнительные материалы
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
}
И последнее напоминание: в коде, показанном на этой странице, отсутствуют важные операции, обеспечивающие безопасность. Убедитесь, что ваш производственный код включает такие операции.