В этом посте поговорим о мета блоках, почему их стоит использовать, а так же разберем парочку реальных примеров использования.
Что такое мета блоки?
Когда пользователь редактирует пост, на его экране показываются разные поля: редактирование поста, кнопки добавления его в черновик или удалить, выбрать категорию, теги и прочее. Эти поля называются «мета блоки». Плагины могут добавлять собственные мета блоки на странице редактирования любого типа поста.
Контент мета блока — это как правило HTML элементы, например, форма, где пользователь что-то вводит относящееся к плагину или не обязательно к нему. По сути, там может быть всё что угодно.
Почем стоит использовать мета блоки?
Мета блоки — это удобные, гибкие и легко настраиваемые блоки на экране редактирования поста, которые помогают собрать информацию относящуюся к нему.
Мета блоки могут быть скрыты пользователем, если это ему потребуется. Многие из них предоставляют возможность переноса блока мышью посредством drag & drop. Пользователи могут по разному сортировать их, настраивая рабочую среду для написания постов так, как ему комфортно.
Все примеры представленные на этой странице сделаны с целью демонстрации. Не используйте их в реальных плагинах.
Безопасность, настройка прав пользователей, nonces, перевод и прочие тонкости были опущены в этих примерах, так как не являются основной целью этой записи. Для этого были написаны отдельные посты, подробно описывающие эти процессы.
Добавление мета блоков
Используйте функцию add_meta_box()
для добавления мета блока и используйте хук add_meta_boxes
для добавления в список всех блоков.
Пример ниже добавит мета блок на страницу редактирования поста, а так же на bologer_cpt
.
function bologer_add_custom_box() { $screens = ['post', 'bologer_cpt']; foreach ($screens as $screen) { add_meta_box( 'wporg_box_id', // уникальный ID 'Собственный заголовок', // Заголовок блока 'bologer_custom_box_html', // callback функция для вывода HTML, должна быть вызываемого типа $screen // Виды постов ); } } add_action('add_meta_boxes', 'bologer_add_custom_box');
Функция bologer_custom_box_html
будет использоваться как HTML контент для выводимого блока.
Пример ниже добавляет элементы формы, лейблы и другие HTML элементы в мета блок:
function bologer_custom_box_html($post) { ?> <label for="bologer_field">Описание поля</label> <select name="bologer_field" id="bologer_field" class="postbox"> <option value="">Выбрать...</option> <option value="opt1">Один</option> <option value="opt2">Два</option> </select> <?php }
Обратите внимание на то, что в списке элементов нет кнопок и самого тега формы, так как все поля будут сохранены в базу когда вы нажмете «Опубликовать» или «Обновить» пост. После нажатия сделается POST запрос, который захватит все поля формы со страницы, включая ваш мета блок.
Пример выше добавляет лишь один элемент формы — выпадающий список. Вы же можете создавать безграничное кол-во элементов формы, но помните, что важно сохранять правильную структуру ваших полей, поэтому группируйте их в коде и визуально, чтобы в дальнейшем с ними можно было легко работать.
Получение значений
Чтобы получить сохраненные данные из мета блока, вам нужно достать их от туда где вы их изначально сохранили. Если они были сохранены в таблице postmeta
, тогда это можно сделать используя функцию get_post_meta()
.
Следующий пример — это улучшение предыдущего примера с формой. Теперь после сохранения данных в форме, они будут заранее выбраны. Чуть ниже в этом посте мы разберем как сохранять значения из формы.
function bologer_custom_box_html($post) { $value = get_post_meta($post->ID, '_wporg_meta_key', true); ?> <label for="bologer_field">Описание поля</label> <select name="bologer_field" id="bologer_field" class="postbox"> <option value="">Выбрать...</option> <option value="opt1" <?php selected($value, 'opt1'); ?>>Один</option> <option value="opt2" <?php selected($value, 'opt2'); ?>>Два</option> </select> <?php }
Подробнее о selected().
Сохранение значение
Когда тип поста сохранен или изменен — в этот момент вызывается пару действий, некоторые из которых можно занести в хук, чтобы сохранить введенные данные. В этом пример, мы используем хук действия — save_post
, но в некоторых случаях желательно практиковать другие хуки. Так же обратите внимание на то, что save_post
может быть вызван более чем один раз, во время обновления поста.
Вы можете сохранить введенную информацию куда вам нужно, даже за границей WordPress, но так как вы имеете дело с информацией связанной с конкретным постом, лучше всего заносить её в таблицу postmeta
.
Следующий пример сохранит значение поля bologer_field
под ключом _bologer_meta_key
, который скрыт.
function bologer_save_postdata($post_id) { if (array_key_exists('bologer_field', $_POST)) { update_post_meta( $post_id, '_bologer_meta_key', $_POST['bologer_field'] ); } } add_action('save_post', 'bologer_save_postdata');
Помните, чтобы вам нужно помнить о безопасности, если вы собираетесь использовать такой код в продакшине.
Что происходит за кулисами
Обычно вам не нужно знать о том, что происходит за кулисами (на заднем плане), но данная секция была добавлена для полноты картины.
Когда пост хочет отобразить все мета блоки, вызывается do_meta_blocks()
. Эта функцию циклично проходится по всем объявленным мета блокам и вызывает callback функции связанные с каждым из них. Тем самым выводит весь контент из функции (например, div’ы, заголовки и пр.).
Удаление мета блоков
Для удаления существующих мета блоков с экрана редактирования поста, вы можете использовать функции remove_meta_box()
. Пускаемые параметры должны быть точно такими же как те, которые использовались при добавлении мета блока в функцию add_meta_box()
.
Для удаления мета блоков по умолчанию, смотрите в исходный код и какие параметры там указаны. Код добавляемых мета блоков по умолчанию находится в wp-includes/edit-form-advanced.php
.
Варианты решений разработки
До текущего момент, мы использовали процедурный способ программирования. Но некоторые разработчики захотят ООП или что-то другое.
OOP
Добавление мета блоков с OOP — это просто и убережет вас от волнения по поводу столкновения с другими именами функций.
Ниже вы можете посмотреть пример абстрактного класса со статическими методами. Сделано это было с целью сохранения памяти и просты использования методов.
abstract class Bologer_Meta_Box { public static function add() { $screens = ['post', 'wporg_cpt']; foreach ($screens as $screen) { add_meta_box( 'wporg_box_id', // уникальное ID 'Собственный заголовок', // Заголовок мета блока [self::class, 'html'], // callback, должен быть типа callable $screen // формат поста ); } } public static function save($post_id) { if (array_key_exists('bologer_field', $_POST)) { update_post_meta( $post_id, '_bologer_meta_key', $_POST['bologer_field'] ); } } public static function html($post) { $value = get_post_meta($post->ID, '_bologer_meta_key', true); ?> <label for="bologer_field">Описание поле</label> <select name="bologer_field" id="bologer_field" class="postbox"> <option value="">Выбрать...</option> <option value="opt1" <?php selected($value, 'opt1'); ?>>Один</option> <option value="opt2" <?php selected($value, 'opt2'); ?>>Два</option> </select> <?php } } add_action('add_meta_boxes', ['Bologer_Meta_Box', 'add']); add_action('save_post', ['Bologer_Meta_Box', 'save']);
AJAX
Так как HTML элементы внутри мета блока — это обычные элементы формы на экране изменения поста то типичными поведением будет обработка данных из глобальной переменной $_POST при сохранении или обновлении поста.
Но вы можете сделать более современный вариант формы добавив AJAX; это позволит пользователям управлять мета блоком без нажатия кнопки сохранения/обновления поста.
Установка тригера
Для начала, вам нужно установить триггер, это может быть нажатие на ссылку или любое другое JavaScript событие.
В примере ниже, мы используем событие change
при котором будет выполняться AJAX запрос.
(function ($, window, document) { 'use strict'; // запустить только когда DOM будет готов $(document).ready(function () { // js 'change' событие вызываемое при изменении поля bologer_field $('#bologer_field').on('change', function () { // наш дальнейший код }); }); }(jQuery, window, document));
Клиентская часть
Далее нам нужно определить, что триггер должен делать, иными словами — написать клиентскую часть кода, где будет производиться запрос и прочее.
В примере ниже, мы будем использовать POST запрос, в ответ мы будем получать sucess
или failure
— это будет индикатором правильности ввода поля bologer_field
.
(function ($, window, document) { 'use strict'; // запустить только когда DOM будет готов $(document).ready(function () { // js 'change' событие вызываемое при изменении поля bologer_field $('#bologer_field').on('change', function () { // jQuery post метод, краткий формат $.ajax с POST $.post(bologer_meta_box_obj.url, // или ajaxurl { action: 'wporg_ajax_change', // POST данные, action wporg_field_value: $('#wporg_field').val() // POST данные, wporg_field_value }, function (data) { // проверка data if (data === 'success') { // что-то делаем при success } else if (data === 'failure') { // что-то делаем при failure } else { // что-то делаем, если ничего не вернулось } } ); }); }); }(jQuery, window, document));
Объект bologer_meta_box_obj
будет создан чуть ниже.
Если ваш мета блок запрашивает только WordPress AJAX ссылку, то лучше использовать
ajaxurl
— это по умолчанию предопределенная переменная от WordPress, которая доступна только в админ панели. Но обязательно проверьте, что она не пустая, преждем чем использовать её.
Вывод данных после запроса
Следующий этап — это сделать запрос к файлу и вывод данных.
В примере ниже, мы добавим AJAX функционал к странице редактирования поста на следующие типы постов: post, bologer_cpt.
Файл скрипта будет находится по следующему пути: /nazvanie-plugina/admin/meta-boxes/js/admin.js
, где nazvanie-plugina
— это название папки с вашим плагином,
/nazvanie-plugina/plugin.php
— это файл, который будет вызывать функцию.
function bologer_meta_box_scripts() { // получить текущий экран администратора или null $screen = get_current_screen(); // проверяем, что экран администратора - это объект if (is_object($screen)) { // что мы делаем запрос только на определенные типы постов if (in_array($screen->post_type, ['post', 'bologer_cpt'])) { // добавляем JS скрипт и указываем, что он имеет зависимость от jQuery wp_enqueue_script('bologer_meta_box_script', plugin_dir_url(__FILE__) . 'admin/meta-boxes/js/admin.js', ['jquery']); // добавляем новый js объект wp_localize_script( 'bologer_meta_box_script', 'bologer_meta_box_obj', [ 'url' => admin_url('admin-ajax.php'), ] ); } } } add_action('admin_enqueue_scripts', 'bologer_meta_box_scripts');
Серверный код
Самый последний этап — это добавление серверного обработчика AJAX запроса.
function bologer_meta_box_ajax_handler() { if (isset($_POST['bologer_field_value'])) { switch ($_POST['bologer_field_value']) { case 'opt1': echo 'success'; break; default: echo 'failure'; break; } } // ajax обработчик должен умереть die; } // wp_ajax_ - это префикс, bologer_ajax_change - это название действия, которые мы называли на стороне клиента, когда писали AJAX запрос add_action('wp_ajax_bologer_ajax_change', 'bologer_meta_box_ajax_handler');
И самое последнее напоминание: примеры представленные на этой странице могу быть не в полной мере безопасными. Поэтому если вы планируете что-то использоваться из этого в продакшине — обязательно подумайте о безопасности.