PostMeta — это функционал произвольных полей. В данной статье будет рассматриваться тема использования PostMeta без плагина Advanced Custom Fields.
Включаем в интерфейсе настроек записи Произвольные поля. В поле имя вписываем название поля (!только латинские и желательно одним словом), в значение вписываем содержимое поля. Если в одном поле несколько значений, нужно создавать несколько полей с одним и тем же полем, но разными значениями.
Спустя время убедился в обратном, что в простых случая лучше использовать стандартный функционал PostMeta. ACF конечно мощный инструмент, но и создает кучу лишнего кода и засоряет базу данных (на одно поле создает 2 записи).
Правильное создание дополнительного поля (PostMeta)
Правильное, в том смысле, что при сохранении записи поле не заполнено то удаляется пустая запись из базы данных.
// Произвольное поле
add_action('add_meta_boxes', 'link_box');
function link_box() { add_meta_box('testfield_box', 'Ссылка слайда', 'atb_box_func', 'post', 'normal', 'high'); }
function atb_box_func($post){
$testfield = get_post_meta($post->ID, 'testfield', 1);
?>
<label><input style="width:100%;" type="text" name="extra[testfield]" value="<?php if($testfield){echo $testfield;}?>" /></label>
<input type="hidden" name="atb_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>" />
<?php
}
add_action('save_post', 'atb_box_update');
function atb_box_update($post_id){
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // Проверка, что это не автосохранение
if (!current_user_can('edit_post', $post_id)) return false; // Проверка, что пользователь может изменять этот пост
if (!isset($_POST['extra']) ) return false; // Проверка, что нам пришли все поля
foreach($_POST['extra'] as $key=>$value){ // Циклом добавляем поля. Можно и в ручную это делать... Но так проще добавить новое поле
if (empty($value)) { delete_post_meta($post_id, $key); }
else { update_post_meta($post_id, $key, $value); }
}
}
Последний блок сохранения может быть общим для нескольких полей — надо подумать об этом.
Заведение полей массивом
Этот способ подходит для полей типа input
// Дополнительные поля
add_action('add_meta_boxes', 'speclink_box');
function speclink_box() {
add_meta_box('speclink_box', 'Дополнительные поля', 'speclink_box_func', 'post', 'normal', 'high');
}
function speclink_box_func($post){
$fields = array(
'price'=> 'Цена',
'brand'=> 'Бренд',
'color'=> 'Цвет',
);
foreach ($fields as $field => $name) {
$field_val = get_post_meta($post->ID, $field, 1);
?>
<label style="width:100%;"><?php echo $name; ?> <input type="text" name="extra[<?php echo $field; ?>]" value="<?php if($field_val){ echo $field_val; } ?>" /></label>
<?php
} ?>
<input type="hidden" name="atb_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>" />
<?php
}
add_action('save_post', 'speclink_box_update');
function speclink_box_update($post_id){
if (!wp_verify_nonce($_POST['atb_nonce'], __FILE__)) return false; // Проверка, что сохраняется именно нужная нам страница.
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // Проверка, что это не автосохранение
if (!current_user_can('edit_post', $post_id)) return false; // Проверка, что пользователь может изменять этот пост
if(!isset($_POST['extra']) ) return false; // Проверка, что нам пришли все поля
foreach($_POST['extra'] as $key=>$value){ // Циклом добавляем поля. Можно и в ручную это делать... Но так проще добавить новое поле
if(empty($value) AND $value != 0){ // Если значение пустое и не равно 0
delete_post_meta($post_id, $key); // Удаляем это поле из мета-данных
continue; // Продолжаем
}
update_post_meta($post_id, $key, $value); // Обновляем или добавляем мета-данные
}
return $post_id;
}
Пользовательские типы записей
Включение произвольных полей в пользовательских типах записей. track — это название произвольного типа записей.
// Произвольные поля для пользовательского типа записей function true_custom_fields() { add_post_type_support( 'track', 'custom-fields'); // в качестве первого параметра укажите название типа поста } add_action('init', 'true_custom_fields');
Вывод данных
Вывести все метаданные записи
<?php the_meta(); ?>
Вывести конкретное поле (если значение единственное)
<?php echo get_post_meta($post->ID, 'film', true); ?>
Вывести конкретное поле (если значений несколько)
<?php $items = get_post_meta($post->ID, 'film', false); ?> <?php foreach ( $items as $item) { echo "<p>$item</p>"; } ?>
Вывести поле с данными содержащими тэги html (например если поле заполняется в редакторе wysiwyg)
<?php print htmlspecialchars_decode(get_post_meta($post->ID, 'tehparam', true)); ?>
Вывести поле с проверкой: заполнено ли метаполе. Это нужно, чтобы не выводить в верстке пустые тэги, при незаполненном поле.
<?php if(get_post_meta($post->ID, 'film', true)): ?> <?php echo get_post_meta($post->ID, 'film', true); ?> <?php endif; ?>
Парсим значение метаполя по запятым
Предположим что у нас текстовое поле и мы вводим несколько значений через запятую, например ссылки для youtube (7f2wg1pqQDs, 75TLVk_yxS4, StZcUAPRRac). И чтобы вывести 3 ролика нужно разделить строку на массив:
<?php $videos = preg_replace("/\s+/", "", get_post_meta($post->ID, 'video', 1));
if (!empty($videos)) : ?>
<div class="posts-archive">
<?php $videos_array = explode(",", $videos);
foreach ($videos_array as $video) : ?>
<div class="hentry"><div class="youtube" data-embed="<?php echo $video; ?>"><div class="play-button"></div></div></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
В данном решении для видео использован метод отложенной загрузки.
Вывод списка метаполей для произвольных типов записей
Создаем функцию
function generate_meta_keys(){
global $wpdb;
$post_type = 'shop_order';
$query = "
SELECT DISTINCT($wpdb->postmeta.meta_key)
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta
ON $wpdb->posts.ID = $wpdb->postmeta.post_id
WHERE $wpdb->posts.post_type = '%s'
AND $wpdb->postmeta.meta_key != ''
AND $wpdb->postmeta.meta_key NOT RegExp '(^[_0-9].+$)'
AND $wpdb->postmeta.meta_key NOT RegExp '(^[0-9]+$)'
";
$meta_keys = $wpdb->get_col($wpdb->prepare($query, $post_type));
return $meta_keys;
}
Выводим метаполя custom_post. Нужно понимать что выведутся все метаполя, а не поля текущей записи произвольного типа.
echo '<pre>';
print_r (generate_meta_keys());
echo '</pre>';
Альтернативный способ вывода метаполей
Данный способ может примется к любым метаполям, но он будет выдавать только первый результат, т.е. для полей с несколькими значения не подходит. Идеально для ситуаций, когда требуется выводить несколько полей.
В цикле вывода записи добавляем следующий вызов (код позаимствовал на сайте wp-kama.ru):
$meta = new stdClass;
foreach( (array) get_post_meta( $post->ID ) as $k => $v ) $meta->$k = $v[0];
Теперь любое метаполе можно вывести по слагу так:
echo $meta->book;
Тоже решение, но с другим (более понятным) синтаксисом:
$current_post_meta = get_post_meta($post_id);
foreach ($current_post_meta as $meta_key => $meta_value) {
$current_post_meta[$meta_key] = $meta_value[0];
}
Выводиться так:
echo $current_post_meta['aname'];
Есть один недостаток, если при выводе в цикле у какой-либо записи не будет данного поля то последует предупреждение Undefined index: aname in. Чтобы этого избежать можно делать такой вывод:
echo @$current_post_meta['aname'];
@ — символ экранирования подобных предупреждений.
Проверка пустое поле или нет:
<?php if (empty($current_post_meta['aname'])) {
echo 'пустое';
} else {
echo 'не пустое';
} ?>
Мета поле только для определенной категории
Чтобы выводить мета поле для определенной категории, нужно первую функцию (внутри) обернуть в условие:
function myplugin_add_price_box() {
$categories = get_the_category();
if ($categories[0]->term_id == '2' ) {
add_meta_box( 'myplugin_section_price', 'Цена', 'wp_editor_price_box', 'post' );
}
}
Метабоксы обязательно должны добавляться хуком add_meta_boxes
add_action('add_meta_boxes', 'wysiwyg_register_params_meta_box');
Если, например, добавлять метабокс с так:
add_action('admin_init', 'wysiwyg_register_params_meta_box');
то условие по категории работать не будет, т.к. в тот момент эта глобальная еще не определена.
[site-socialshare]