/ Wordpress / PostMeta

PostMeta

HIT

07.03.2016

3572

PostMeta — это функционал произвольных полей. В данной статье будет рассматриваться тема использования PostMeta без плагина Advanced Custom Fields.

Включаем в интерфейсе настроек записи Произвольные поля. В поле имя вписываем название поля (!только латинские и желательно одним словом), в значение вписываем содержимое поля. Если в одном поле несколько значений, нужно создавать несколько полей с одним и тем же полем, но разными значениями.

Данный стандартный функционал сильно уступает плагину 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; ?>

В данном решении для видео использован метод отложенной загрузки.

preg_replace(«/\s+/», «», $stroke); — удаление из строки пробелов

Вывод списка метаполей для произвольных типов записей

Создаем функцию

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]
  • Комментарии
  • Вложения

Добавить комментарий

Notice: Функция WP_Styles::add вызвана неправильно. Стиль с дескриптором "editor-buttons" был поставлен в очередь с незарегистрированными зависимостями: dashicons. Дополнительную информацию можно найти на странице «Отладка в WordPress». (Это сообщение было добавлено в версии 6.9.1.) in /home/t/tiberi6w/opttour.ru/public_html/wp-includes/functions.php on line 6170

Пока нет комментариев. Будь первым!

PostMeta
Сортировка постов (по дате, по заголовку, по дате изменений)
Рекомендации для васСортировка постов (по дате, по заголовку, по дате изменений)Opttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.