Статьи

Как создавать собственные WordPress записи / мета-боксы

Создание мета-блоков является важной частью разработки темы / плагина WordPress . Это способ добавления привлекательного редактора на экран поста, позволяющий избежать необходимости заставлять пользователей полагаться на пользовательские поля. Если вы когда-либо создавали пользовательский тип записей в WordPress, вы, вероятно, хотели бы добавить к нему какие-то дополнительные данные. Конечно, вы можете использовать настраиваемые поля , но это ужасно. Начать работу с пользовательскими метабоксами легко, поэтому давайте углубимся!


Пользовательская мета (или запись) коробка невероятно проста в теории. Это позволяет вам добавить пользовательский фрагмент данных к сообщению или странице в WordPress.

Представьте, что вы работаете над темой для клиента, который хочет каталогизировать свою обширную коллекцию концертных плакатов. Вы сразу же начинаете искать основную функциональность WordPress, чтобы увидеть, как вы можете организовать тему: каждый пост будет представлять постер, который идеально подходит для добавления изображения, заголовка и описания. Мы также можем использовать систему категорий и тегов в WordPress для организации постеров. Но что, если мы хотим добавить новый тип метаданных для «исполнителя» каждого постера? Хммм. WordPress не имеет ничего для этого прямо из коробки … что приводит нас к настраиваемым метабоксам.

Пользовательская мета (или запись) коробка невероятно проста в теории. Он позволяет вам добавлять пользовательский фрагмент данных к сообщению или странице в WordPress — более того, он может вписываться непосредственно в большинство страниц по умолчанию в WP, поэтому вы можете легко поместить его в Post-Editor для удобного использования нетехнические типы. Как я уже говорил во вступлении, вы можете добавить такие же «метаданные» к вашему сообщению, используя встроенные настраиваемые поля для сообщения или страницы. В этом нет ничего плохого, но это не очень изящно и не удобно для пользователя.

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

  • Добавление мета-блока
  • Рендеринг метабокса
  • Сохранение данных ( правильный путь — да, неправильный путь)

Стоит отметить, что большая часть этой информации также может быть использована в API пользовательских типов записей (мы вернемся к этому вопросу позже!), Но ради того, чтобы держать вещи в фокусе сегодня, мы собираемся добавить это непосредственно к редактор сообщений по умолчанию.

Для продвинутых читателей в аудитории: Да, пользовательские типы постов — это то, к чему мы в конечном итоге пойдем, но сначала важно настроить некоторые основы. Кроме того, поскольку вы можете использовать собственные мета-блоки в самых разных местах, это будет полезно для всех.

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


Название Meta Box

Удобно, 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’ );
}
?>

Приведенного выше кода достаточно для добавления мета-блока, но теперь мы должны отобразить объект и фактически добавить поля. Это просто код формы 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
&lt?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, поэтому мы проверяем, что одноразовый номер действителен, прежде чем что-либо делать.

Правило номер один при помещении чего-либо в вашу базу данных или на ваш сайт — не доверяйте пользователю . Даже если этот пользователь — ты.

Чтобы сохранить наши данные, мы будем полагаться на другую ловушку 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).