Создание мета-блоков является важной частью разработки темы / плагина WordPress . Это способ добавления привлекательного редактора на экран поста, позволяющий избежать необходимости заставлять пользователей полагаться на пользовательские поля. Если вы когда-либо создавали пользовательский тип записей в WordPress, вы, вероятно, хотели бы добавить к нему какие-то дополнительные данные. Конечно, вы можете использовать настраиваемые поля , но это ужасно. Начать работу с пользовательскими метабоксами легко, поэтому давайте углубимся!
Что такое пользовательские мета-боксы?
Пользовательская мета (или запись) коробка невероятно проста в теории. Это позволяет вам добавить пользовательский фрагмент данных к сообщению или странице в WordPress.
Представьте, что вы работаете над темой для клиента, который хочет каталогизировать свою обширную коллекцию концертных плакатов. Вы сразу же начинаете искать основную функциональность WordPress, чтобы увидеть, как вы можете организовать тему: каждый пост будет представлять постер, который идеально подходит для добавления изображения, заголовка и описания. Мы также можем использовать систему категорий и тегов в WordPress для организации постеров. Но что, если мы хотим добавить новый тип метаданных для «исполнителя» каждого постера? Хммм. WordPress не имеет ничего для этого прямо из коробки … что приводит нас к настраиваемым метабоксам.
Пользовательская мета (или запись) коробка невероятно проста в теории. Он позволяет вам добавлять пользовательский фрагмент данных к сообщению или странице в WordPress — более того, он может вписываться непосредственно в большинство страниц по умолчанию в WP, поэтому вы можете легко поместить его в Post-Editor для удобного использования нетехнические типы. Как я уже говорил во вступлении, вы можете добавить такие же «метаданные» к вашему сообщению, используя встроенные настраиваемые поля для сообщения или страницы. В этом нет ничего плохого, но это не очень изящно и не удобно для пользователя.
Вместо этого вы хотите создать пользовательский мета-блок, который содержит поля для всех ваших данных и сохраняет все эти вещи прямо при публикации публикации. Это то, что мы здесь освещаем. Это разбито на три больших шага:
- Добавление мета-блока
- Рендеринг метабокса
- Сохранение данных ( правильный путь — да, неправильный путь)
Стоит отметить, что большая часть этой информации также может быть использована в API пользовательских типов записей (мы вернемся к этому вопросу позже!), Но ради того, чтобы держать вещи в фокусе сегодня, мы собираемся добавить это непосредственно к редактор сообщений по умолчанию.
Для продвинутых читателей в аудитории: Да, пользовательские типы постов — это то, к чему мы в конечном итоге пойдем, но сначала важно настроить некоторые основы. Кроме того, поскольку вы можете использовать собственные мета-блоки в самых разных местах, это будет полезно для всех.
Все в этом уроке будет работать в файле functions.php темы. Это не правильное место для этого, однако. Если вы добавляете данные в сообщение, скорее всего, вы хотите, чтобы они там были, независимо от вашего внешнего интерфейса. Таким образом, вы должны поместить этот код в место, не зависящее от вашего дизайна: файл плагина.
Шаг 1 Добавление мета-бокса

Удобно, WordPress предоставляет функцию для добавления мета-полей на заданный экран администратора: add_meta_box .
Запись кодекса хорошо сделана для этой функции, но вот краткий обзор. Его прототип:
|
1
|
<?php add_meta_box( $id, $title, $callback, $page, $context, $priority, $callback_args );
|
$id — это атрибут html ID этого поля. Это полезно, если вы загружаете пользовательский CSS или Javascript на страницу редактирования для обработки параметров. В противном случае, это не имеет большого значения.
$title отображается в верхней части мета-поля.
$callback — это функция, которая фактически отображает метабокс. Мы опишем это на шаге 2.
$page — это то место, где вы хотите отобразить метаблок. Это должна быть строка с ‘post’ или ‘page’ или ‘some_custom_post_type’.
$context — это то место, где вы хотите отобразить мета-поле. ‘normal’ помещает его ниже редактора сообщений. ‘side’ перемещает мета-поле в правую боковую панель редактирования (по категориям, тегам и т. д.). ‘advanced’ также помещает флажок в тот же столбец, что и редактор сообщений, но дальше вниз.
$priority сообщает wordpress, где разместить мета-блок в контексте. ‘high’, ‘default’ или ‘low’ помещают коробку ближе к вершине, в ее нормальное положение или к нижней части соответственно. Поскольку все мета-блоки можно перетаскивать, $priority не так уж значителен.
Наконец, $callback_args позволяет передавать данные в $callback в виде массива. Мы не собираемся использовать это здесь, но это может быть полезно для передачи некоторых данных в мета-блок. Скажем, если у вашего плагина было несколько опций, которые влияли на то, что отображалось в мета-окне. Вы можете передать значения этих опций через массив $callback_args .
Итак, наш вызов add_meta_box будет выглядеть так:
|
1
|
<?php add_meta_box( ‘my-meta-box-id’, ‘My First Meta Box’, ‘cd_meta_box_cb’, ‘post’, ‘normal’, ‘high’ );
|
Мы не можем просто вставить это в наш файл плагина в одиночку. Это приведет к белому экрану смерти и фатальной ошибке PHP: вызов неопределенной функции. Почему? Потому что мы add_meta_box функцию add_meta_box до загрузки WordPress. Поэтому нам нужно использовать хук WordPress, который является частью API плагина . По сути, функции подключаются к заданному действию WordPress или фильтру, затем эти функции запускаются при загрузке. Оборачивая наш вызов add_meta_box в функцию, затем подключая эту функцию к add_meta_boxes действия add_meta_boxes , мы избегаем фатальной ошибки.
Наш код для добавления мета-блока на наш экран постов будет выглядеть так:
|
1
2
3
4
5
6
7
|
<?php
add_action( ‘add_meta_boxes’, ‘cd_meta_box_add’ );
function cd_meta_box_add()
{
add_meta_box( ‘my-meta-box-id’, ‘My First Meta Box’, ‘cd_meta_box_cb’, ‘post’, ‘normal’, ‘high’ );
}
?>
|
Шаг 2 Рендеринг мета-бокса
Приведенного выше кода достаточно для добавления мета-блока, но теперь мы должны отобразить объект и фактически добавить поля. Это просто код формы HTML, смешанный с небольшим количеством PHP для отображения сохраненных данных. Нам не нужно включать теги формы, поскольку WordPress делает это для нас.
Помните строку, которую мы передали как $callback в add_meta_box ? Теперь мы собираемся создать функцию с тем же именем. Эта функция позаботится обо всем отображении внутри мета-блока.
|
1
2
3
4
5
6
|
<?php
function cd_meta_box_cb()
{
echo ‘What you put here, show\’s up in the meta box’;
}
?>
|

Мы собираемся добавить несколько полей в наш мета-блок: ввод текста, раскрывающееся меню и флажок. Начнем с ввода текста.
Добавление ввода текста
|
1
2
3
4
5
6
7
8
9
|
<?php
function cd_meta_box_cb()
{
?>
<label for=»my_meta_box_text»>Text Label</label>
<input type=»text» name=»my_meta_box_text» id=»my_meta_box_text» />
<?php
}
?>
|

Но как насчет отображения данных? Итак, как вы увидите на шаге 3, мы будем хранить эти данные в таблице wp_postmeta с помощью функции update_post_meta. Эта функция имеет две родственные функции: get_post_meta и get_post_custom , которые получают данные из wp_postmeta. get_post_meta данные только с одного ключа, а get_post_custom все. Поскольку на данный момент мы используем только одно поле, давайте использовать get_post_meta .
Также обратите внимание, что функция add_meta_box передает одну переменную нашему add_meta_box вызову: $ post, который является объектом post.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<?php
function cd_meta_box_cb( $post )
{
$values = get_post_custom( $post->ID );
$text = isset( $values[‘my_meta_box_text’] ) ?
$selected = isset( $values[‘my_meta_box_select’] ) ?
$check = isset( $values[‘my_meta_box_check’] ) ?
?>
<p>
<label for=»my_meta_box_text»>Text Label</label>
<input type=»text» name=»my_meta_box_text» id=»my_meta_box_text» value=»<?php echo $text; ?>» />
</p>
<?php
}
?>
|
Добавление выпадающего
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?php
function cd_meta_box_cb( $post )
{
$values = get_post_custom( $post->ID );
$text = isset( $values[‘my_meta_box_text’] ) ?
$selected = isset( $values[‘my_meta_box_select’] ) ?
$check = isset( $values[‘my_meta_box_check’] ) ?
?>
<p>
<label for=»my_meta_box_text»>Text Label</label>
<input type=»text» name=»my_meta_box_text» id=»my_meta_box_text» value=»<?php echo $text; ?>» />
</p>
<p>
<label for=»my_meta_box_select»>Color</label>
<select name=»my_meta_box_select» id=»my_meta_box_select»>
<option value=»red» <?php selected( $selected, ‘red’ );
<option value=»blue» <?php selected( $selected, ‘blue’ );
</select>
</p>
<?php
}
?>
|
С добавлением второго поля мы изменили или вызов get_post_meta для get_post_custom , который возвращает ассоциативный массив всех пользовательских ключей и значений сообщения. Затем мы просто получаем доступ к нашим полям через их имена. Тернарные операторы удерживают наш код от выдачи предупреждений PHP (неопределенные индексы и тому подобное). Мы рассмотрим функцию esc_attr на третьем шаге.
В раскрывающемся списке мы будем использовать одну из самых удобных функций WordPress: выбранный . Это сравнивает первое значение, данные, которые мы сохранили, со вторым, атрибутом значения <option> . Если они одинаковы, функция echo selected="selected" отображает это значение в раскрывающемся списке. Довольно мило, и это спасает нас от написания множества слов if или ternary. Вы также можете использовать функцию selected() с переключателями.
Добавление флажка
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<?php
function cd_meta_box_cb()
{
// $post is already set, and contains an object: the WordPress post
global $post;
$values = get_post_custom( $post->ID );
$text = isset( $values[‘my_meta_box_text’] ) ?
$selected = isset( $values[‘my_meta_box_select’] ) ?
$check = isset( $values[‘my_meta_box_check’] ) ?
// We’ll use this nonce field later on when saving.
wp_nonce_field( ‘my_meta_box_nonce’, ‘meta_box_nonce’ );
?>
<p>
<label for=»my_meta_box_text»>Text Label</label>
<input type=»text» name=»my_meta_box_text» id=»my_meta_box_text» value=»<?php echo $text; ?>» />
</p>
<p>
<label for=»my_meta_box_select»>Color</label>
<select name=»my_meta_box_select» id=»my_meta_box_select»>
<option value=»red» <?php selected( $selected, ‘red’ );
<option value=»blue» <?php selected( $selected, ‘blue’ );
</select>
</p>
<p>
<input type=»checkbox» id=»my_meta_box_check» name=»my_meta_box_check» <?php checked( $check, ‘on’ );
<label for=»my_meta_box_check»>Do not check this</label>
</p>
<?php
}
?>
|
Снова WordPress предоставляет удобную функцию checked () . Он работает так же, как selected() сравнивая первое значение (наши сохраненные данные) со вторым и выводя checked="checked" selected() checked="checked" если они совпадают.
wp_nonce_field добавляет два скрытых поля в наш мета-блок. Одним из них является одноразовый номер . Это случайные строки чисел, которые действительны для каждого пользователя в течение 24 часов. Одноразовые номера — это способ проверки намерения, и они удостоверяются, что WordPress ничего не делает, если запрос не поступил из очень определенного места. Другими словами, мы не хотим случайно обновить наши данные, запустив функцию сохранения (см. Шаг 3) в другом месте, отличном от ловушки save_post, поэтому мы проверяем, что одноразовый номер действителен, прежде чем что-либо делать.

Шаг 3 Сохранение данных
Правило номер один при помещении чего-либо в вашу базу данных или на ваш сайт — не доверяйте пользователю . Даже если этот пользователь — ты.
Чтобы сохранить наши данные, мы будем полагаться на другую ловушку WordPress: save_post . Это работает так же, как наш хук действия выше:
|
1
|
<?php add_action( ‘save_post’, ‘cd_meta_box_save’ );
|
Функция cd_meta_box_save получит один аргумент, идентификатор записи и позаботится об очистке и сохранении всех наших данных. save_post срабатывает после нажатия кнопки обновления или сохранения черновика. Таким образом, у нас есть доступ ко всем данным $_POST , включая поля мета-поля, в нашей функции сохранения. Однако прежде чем мы сможем что-либо сделать, нам нужно сделать три вещи: проверить, является ли публикация автосохранением, проверить значение nonce, которое мы создали ранее, и убедиться, что текущий пользователь действительно может редактировать сообщение.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<?php
add_action( ‘save_post’, ‘cd_meta_box_save’ );
function cd_meta_box_save( $post_id )
{
// Bail if we’re doing an auto save
if( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE ) return;
// if our nonce isn’t there, or we can’t verify it, bail
if( !isset( $_POST[‘meta_box_nonce’] ) || !wp_verify_nonce( $_POST[‘meta_box_nonce’], ‘my_meta_box_nonce’ ) ) return;
// if our current user can’t edit this post, bail
if( !current_user_can( ‘edit_post’ ) ) return;
}
?>
|
Теперь самое интересное: на самом деле мы сохраняем наши данные. Правило номер один при помещении чего-либо в вашу базу данных или на ваш сайт — не доверяйте пользователю . Даже если этот пользователь — ты. В связи с этим, прежде чем сохранять какие-либо данные, мы хотим убедиться, что в них нет ничего вредоносного. К счастью, WordPress предоставляет множество функций для проверки данных .
Вы уже видели esc_attr() выше (шаг 2). Это кодирует символы «» и <> в сущности HTML. Зачем использовать это? Таким образом, пользователи не могли ввести <script> в ваш мета-блок. Если вы хотите разрешить определенные теги HTML, но лишить других, wp_kses может сделать Это требует двух аргументов, первый из которых — строка, которую вы хотите проверить, а второй — ассоциативный массив разрешенных тегов. WordPress предоставляет гораздо больше инструментов для проверки данных, но не бойтесь их использовать.
Мы собираемся использовать функцию update_post_meta чтобы заботиться о сохранении наших данных. Он принимает три аргумента: идентификатор сообщения, мета-ключ и значение.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
<?php
add_action( ‘save_post’, ‘cd_meta_box_save’ );
function cd_meta_box_save( $post_id )
{
// Bail if we’re doing an auto save
if( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE ) return;
// if our nonce isn’t there, or we can’t verify it, bail
if( !isset( $_POST[‘meta_box_nonce’] ) || !wp_verify_nonce( $_POST[‘meta_box_nonce’], ‘my_meta_box_nonce’ ) ) return;
// if our current user can’t edit this post, bail
if( !current_user_can( ‘edit_post’ ) ) return;
// now we can actually save the data
$allowed = array(
‘a’ => array( // on allow a tags
‘href’ => array() // and those anchors can only have href attribute
)
);
// Make sure your data is set before trying to save it
if( isset( $_POST[‘my_meta_box_text’] ) )
update_post_meta( $post_id, ‘my_meta_box_text’, wp_kses( $_POST[‘my_meta_box_text’], $allowed ) );
if( isset( $_POST[‘my_meta_box_select’] ) )
update_post_meta( $post_id, ‘my_meta_box_select’, esc_attr( $_POST[‘my_meta_box_select’] ) );
// This is purely my personal preference for saving check-boxes
$chk = isset( $_POST[‘my_meta_box_check’] ) && $_POST[‘my_meta_box_select’] ?
update_post_meta( $post_id, ‘my_meta_box_check’, $chk );
}
?>
|

Заворачивать
Это оно! У вас должен быть полностью рабочий метабокс. Другие примеры, которые вы можете найти в веб-цикле по множеству полей, не очищая данные. Это неправильный подход. Всегда используйте встроенные функции проверки данных; разные поля / значения могут требовать различной проверки данных.
Чтобы использовать эти настраиваемые поля в интерфейсе вашего сайта, используйте функции get_post_meta или get_post_custom (см. Шаг 2).