Многие пользователи WordPress часто используют повторяющиеся элементы на сайте, и каждый раз приходится их вставлять, поправлять, находить/изменять или менять положение на сайте, например, автор блога о кулинарии может часто использовать такую информацию: сложность, время, требуемые продукты и т.д. В этом случае гораздо легче будет использовать специальные мета-поля при добавлении записи, а данные, которые мы введем в них, будут автоматически подставляться в заранее созданное для них место. Т.е. к стандартным полям, которые мы заполняем, когда добавляем новую запись в WordPress (Заголовок, Рубрики, Текст записи, Метки), мы добавляем еще свои собственные, пользовательские поля, а затем, используем их в качестве часто используемых, тем самым значительно упрощая процесс.
Или представьте что Вы работаете над проектом клиента, который хочет иметь на сайте свой собственный, обширный каталог музыкальных альбомов. Посмотрев на стандартный функционал WordPress из коробки, вы замечаете, что стандартных возможностей для вывода нужной клиенту информации не хватает, конечно, он может использовать основные возможности: Категории, Метки, Заголовки, Миниатюра записи и т.д., но не хватает таких полей, как Продюсер, Дата выпуска, Список песен в альбоме и т.д. Здесь на помощь приходят metaboxes - дополнительные или, по-другому, кастомные поля.
Вот пример дополнительных полей:
1) Создаем собственную дополнительную секцию для мета полей
Открываем файл function.php
, который расположен в директории с темой вашего сайта.
wp-content/themes/ваша_тема/function.php
И пишем внизу функцию добавления секции для мета-поля:
1 2 3 4 5 6 7 8 9 10 11 |
// Добавляем дополнительное поле function my_meta_box() { add_meta_box( 'my_meta_box', // Идентификатор(id) 'My Meta Box', // Заголовок области с мета-полями(title) 'show_my_metabox', // Вызов(callback) 'post', // Где будет отображаться наше поле, в нашем случае в Записях 'normal', 'high'); } add_action('add_meta_boxes', 'my_meta_box'); // Запускаем функцию |
$callback
— это функция вызова, которая отображает наши поля. Мы опишем её в 3 шаге.
$context
— место, где будет отображаться дополнительное поле.
- «normal» будет отображать запись ниже редактора записи.
- «side» поместить поле в правую часть, там где Рубрики, Метки и т.д.
- «advanced» также поместит их в колонку справа, но в самый низ.
$priority
— не является важным аргументом, он говорит wordpress’у приоритет размещения:
- hight — высокий,
- default — по умолчанию,
- low — низкий.
2) Создаем нужные поля
Продолжаем делать новые записи в файл function.php
Сейчас нам нужно создать сами поля, как вам известно, существуют разные виды полей, например, text, textarea, checkbox, select и т.д. Мы создадим все перечисленные виды, приступим:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
$meta_fields = array( array( 'label' => 'Текстовое поле', 'desc' => 'Описание для поля.', 'id' => 'mytextinput', // даем идентификатор. 'type' => 'text' // Указываем тип поля. ), array( 'label' => 'Большое текстовое поле', 'desc' => 'Описание для поля.', 'id' => 'mytextarea', // даем идентификатор. 'type' => 'textarea' // Указываем тип поля. ), array( 'label' => 'Чекбоксы (флажки)', 'desc' => 'Описание для поля.', 'id' => 'mycheckbox', // даем идентификатор. 'type' => 'checkbox' // Указываем тип поля. ), array( 'label' => 'Всплывающий список', 'desc' => 'Описание для поля.', 'id' => 'myselect', 'type' => 'select', 'options' => array ( // Параметры, всплывающие данные 'one' => array ( 'label' => 'Вариант 1', // Название поля 'value' => '1' // Значение ), 'two' => array ( 'label' => 'Вариант 2', // Название поля 'value' => '2' // Значение ), 'three' => array ( 'label' => 'Вариант 3', // Название поля 'value' => '3' // Значение ) ) ) ); |
Таким образом, мы создали все требуемые нам поля, дали им название и краткое описание. Важно! Используйте уникальный id для каждого поля или используйте префикс например «my», чтобы избежать совпадений с внутренними, системными идентификаторами. Все требуемые поля и информацию о них мы поместили в массив $meta_fields
Используя данный принцип, вы можете размещать сколько угодно различных полей.
3) Выводим наши поля на экран
Сейчас мы опишем функцию callback
, которую мы задавали в 1 шаге.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Вызов метаполей function show_my_metabox() { global $meta_fields; // Обозначим наш массив с полями глобальным global $post; // Глобальный $post для получения id создаваемого/редактируемого поста // Выводим скрытый input, для верификации. Безопасность прежде всего! echo '<input type="hidden" name="custom_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />'; // Начинаем выводить таблицу с полями через цикл echo '<table class="form-table">'; foreach ($meta_fields as $field) { // Получаем значение если оно есть для этого поля $meta = get_post_meta($post->ID, $field['id'], true); // Начинаем выводить таблицу echo '<tr> <th><label for="'.$field['id'].'">'.$field['label'].'</label></th> <td>'; switch($field['type']) { // Выводить поля будем здесь, как это сделать читайте ниже! } echo '</td></tr>'; } echo '</table>'; } |
Теперь по порядку о каждом действии:
- Выводим скрытое поле для сверки, когда мы будем сохранять данные. В это поле будет помещен проверочный код, который мы создаем через функцию
wp_create_nonce()
. Этот уникальный код поможет нам обезопасится от межсайтового скриптинга (XSS атак). - Начинаем таблицу и запускаем цикл, который будет перебирать все наши поля из массива
$custom_meta_fields
. - Получаем значение поля, если раньше оно уже было сохранено, то мы выведем это значение в поле.
- Далее, используя конструкцию
switch-case
, мы будем выводить каждое поле отдельно, т.к. у каждого поля имеются свои атрибуты и теги для вывода. (textarea и input — разные теги). - В конце мы завершаем цикл, закрываем таблицу, и закрываем функцию.
Теперь давайте разберем каждый case
, мы будем перебирать каждое поле по его типу (textarea, text, checkbox) и для каждого типа будем делать свой вывод, через определенные html теги. Для того, чтобы показывать ранее введенную информацию мы использовали выше переменную($meta
), в которую мы будем получать эти данные, если они есть, будем их показывать, если нет, показываем пустое поле. Поехали:
Case: text (текстовое поле)
1 2 3 4 5 |
// Текстовое поле case 'text': echo '<input type="text" name="'.$field['id'].'" id="'.$field['id'].'" value="'.$meta.'" size="30" /> <br /><span class="description">'.$field['desc'].'</span>'; break; |
Здесь все просто: если тип поля "text"
, тогда мы выводим тег input
и подставляем данные из нашего массива в атрибуты тега, затем делаем перенос строки <br /> и выводим описание поля.
Case: textarea (Зона текста)
1 2 3 4 5 |
// Зона Текста case 'textarea': echo '<textarea name="'.$field['id'].'" id="'.$field['id'].'" cols="60" rows="4">'.$meta.'</textarea> <br /><span class="description">'.$field['desc'].'</span>'; break; |
Здесь разница только в том, что следуя стандартам использования textarea
, мы используем $meta
между открывающим и закрывающим тегом, чтобы мы могли выводить любой сохраненный ранее текст.
Case: checkbox (чекбокс)
1 2 3 4 5 |
// Чекбокс case 'checkbox': echo '<input type="checkbox" name="'.$field['id'].'" id="'.$field['id'].'" ',$meta ? ' checked="checked"' : '','/> <label for="'.$field['id'].'">'.$field['desc'].'</label>'; break; |
Использование $meta
в чекбоксе обусловлено тем, что нам необходимо выводить ранее сохранённый выбор пользователя (если таковой есть) и давать этому полю атрибут checked
.
Массив из чекбоксов
В массив с элементами:
1 2 3 4 5 6 7 |
array( 'label' => 'Доступные размеры', //'desc' => '48 - 50 RUS', 'id' => 'mycheckbox', 'type' => 'checkbox', // Указываем тип поля. 'value' => array ('46-48 RUS','48-50 RUS','50-52 RUS','52-54 RUS','54-56 RUS') ), |
В конструкцию switch-case:
1 2 3 4 5 6 7 8 9 |
case 'checkbox': foreach ($field['value'] as $value){ echo '<input type="checkbox" name="mycheckbox[]" value="'.$value.'" id="mycheckbox['.$value.']" '; foreach($meta as $val){ if ($val == $value) echo ' checked="checked";} />';} echo '<label for="mycheckbox['.$value.']">'.$value.'</label>'; } break; |
Вывод на странице:
1 2 3 4 5 6 7 8 9 |
<div class='sizeTovar'> <?php $mass = get_post_meta($post->ID, 'mycheckbox', true); echo '<select>'; foreach ($mass as $value) { echo '<option value="'.$value.'">'.$value.'</option>'; } echo '</select>'; ?> </div> |
Case: Select (список)
1 2 3 4 5 6 7 8 |
// Список case 'select': echo '<select name="'.$field['id'].'" id="'.$field['id'].'">'; foreach ($field['options'] as $option) { echo '<option', $meta == $option['value'] ? ' selected="selected"' : '', ' value="'.$option['value'].'">'.$option['label'].'</option>'; } echo '</select><br /><span class="description">'.$field['desc'].'</span>'; break; |
В данном случае мы, пробегаем по массиву options
и выводим наши <option></option>. Не забываем, что если ранее данные были сохранены, то мы показываем их.
4) Сохраняем введенные в поля данные
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// Пишем функцию для сохранения function save_my_meta_fields($post_id) { global $meta_fields; // Массив с нашими полями // проверяем наш проверочный код if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], basename(__FILE__))) return $post_id; // Проверяем авто-сохранение if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id; // Проверяем права доступа if ('page' == $_POST['post_type']) { if (!current_user_can('edit_page', $post_id)) return $post_id; } elseif (!current_user_can('edit_post', $post_id)) { return $post_id; } // Если все отлично, прогоняем массив через foreach foreach ($meta_fields as $field) { $old = get_post_meta($post_id, $field['id'], true); // Получаем старые данные (если они есть), для сверки $new = $_POST[$field['id']]; if ($new && $new != $old) { // Если данные новые update_post_meta($post_id, $field['id'], $new); // Обновляем данные } elseif ('' == $new && $old) { delete_post_meta($post_id, $field['id'], $old); // Если данных нету, удаляем мету. } } // end foreach } add_action('save_post', 'save_my_meta_fields'); // Запускаем функцию сохранения |
- Принимаем старое значение поля, если оно есть, в переменную
$old
- Принимаем текущее, новое значение с поля в переменную
$new
- Если новые данные отличаются от старых, обновляем данные
- Если новое значение поля пустое, удаляем запись об этом поле
- Если ничего не изменилось — ничего не изменяем
5) Заключение
Как видите, мы прекрасно справились с задачей, результат должен Вас впечатлить. Благодаря простому принципу создания дополнительных полей, мы можем решать любые проблемы связанные с вводом информации. В следующем уроке, мы посмотрим, как получать данные из meta полей. Вот результат нашей работы:
Весь код написанный нами за весь урок выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
function my_meta_box() { add_meta_box( 'my_meta_box', // Идентификатор(id) 'My Meta Box', // Заголовок области с мета-полями(title) 'show_my_metabox', // Вызов(callback) 'post', // Где будет отображаться наше поле, в нашем случае в Записях 'normal', 'high'); } add_action('add_meta_boxes', 'my_meta_box'); // Запускаем функцию $meta_fields = array( array( 'label' => 'Текстовое поле', 'desc' => 'Описание для поля.', 'id' => 'mytextinput', // даем идентификатор. 'type' => 'text' // Указываем тип поля. ), array( 'label' => 'Большое текстовое поле', 'desc' => 'Описание для поля.', 'id' => 'mytextarea', // даем идентификатор. 'type' => 'textarea' // Указываем тип поля. ), array( 'label' => 'Чекбоксы (флажки)', 'desc' => 'Описание для поля.', 'id' => 'mycheckbox', // даем идентификатор. 'type' => 'checkbox' // Указываем тип поля. ), array( 'label' => 'Всплывающий список', 'desc' => 'Описание для поля.', 'id' => 'myselect', 'type' => 'select', 'options' => array ( // Параметры, всплывающие данные 'one' => array ( 'label' => 'Вариант 1', // Название поля 'value' => '1' // Значение ), 'two' => array ( 'label' => 'Вариант 2', // Название поля 'value' => '2' // Значение ), 'three' => array ( 'label' => 'Вариант 3', // Название поля 'value' => '3' // Значение ) ) ) ); // Вызов метаполей function show_my_metabox() { global $meta_fields; // Обозначим наш массив с полями глобальным global $post; // Глобальный $post для получения id создаваемого/редактируемого поста // Выводим скрытый input, для верификации. Безопасность прежде всего! echo '<input type="hidden" name="custom_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />'; // Начинаем выводить таблицу с полями через цикл echo '<table class="form-table">'; foreach ($meta_fields as $field) { // Получаем значение если оно есть для этого поля $meta = get_post_meta($post->ID, $field['id'], true); // Начинаем выводить таблицу echo '<tr> <th><label for="'.$field['id'].'">'.$field['label'].'</label></th> <td>'; switch($field['type']) { case 'text': echo '<input type="text" name="'.$field['id'].'" id="'.$field['id'].'" value="'.$meta.'" size="30" /> <br /><span class="description">'.$field['desc'].'</span>'; break; case 'textarea': echo '<textarea name="'.$field['id'].'" id="'.$field['id'].'" cols="60" rows="4">'.$meta.'</textarea> <br /><span class="description">'.$field['desc'].'</span>'; break; case 'checkbox': echo '<input type="checkbox" name="'.$field['id'].'" id="'.$field['id'].'" ',$meta ? ' checked="checked"' : '','/> <label for="'.$field['id'].'">'.$field['desc'].'</label>'; break; // Всплывающий список case 'select': echo '<select name="'.$field['id'].'" id="'.$field['id'].'">'; foreach ($field['options'] as $option) { echo '<option', $meta == $option['value'] ? ' selected="selected"' : '', ' value="'.$option['value'].'">'.$option['label'].'</option>'; } echo '</select><br /><span class="description">'.$field['desc'].'</span>'; break; } echo '</td></tr>'; } echo '</table>'; } // Пишем функцию для сохранения function save_my_meta_fields($post_id) { global $meta_fields; // Массив с нашими полями // проверяем наш проверочный код if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], basename(__FILE__))) return $post_id; // Проверяем авто-сохранение if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id; // Проверяем права доступа if ('page' == $_POST['post_type']) { if (!current_user_can('edit_page', $post_id)) return $post_id; } elseif (!current_user_can('edit_post', $post_id)) { return $post_id; } // Если все отлично, прогоняем массив через foreach foreach ($meta_fields as $field) { $old = get_post_meta($post_id, $field['id'], true); // Получаем старые данные (если они есть), для сверки $new = $_POST[$field['id']]; if ($new && $new != $old) { // Если данные новые update_post_meta($post_id, $field['id'], $new); // Обновляем данные } elseif ('' == $new && $old) { delete_post_meta($post_id, $field['id'], $old); // Если данных нету, удаляем мету. } } // end foreach } add_action('save_post', 'save_my_meta_fields'); // Запускаем функцию сохранения |
Продолжение урока: позднее...
Привет! Подскажите пожалуйста как решить такую задачу: Идея такова:клиент сначала выбирает стиль услуги(в селект)!в каждом стиле услуги ,разное количество изображений и их размер!Как будет правильно и лучше ,сделать так, что бы в данном стиле выводилось нужное количество полей для изображений и с разными id ,так ,что бы можно было прописать им тумбы ? Буду очень признателен!благодарю!
Как мне кажется, правильно будет сделать так:
Делаешь кастомное поле селект, в котором прописываешь все варианты (к примеру 5 вариантов).
Делаешь на каждый из вариантов 10 (или 20 - сколько их максимум может быть) кастомных полей img с id, привязанными к соответствующей опции select, что-то типа img1_1, img2_2 (заполнять соответственно их все необязательно).
А при выводе всем img ставишь display:none, а на select - onchange - вывод соответствующих img.
Конструкция монструозная, но довольно легко реализуется.