Кастомные типы записей

Регистрация пользовательского типа поста

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

Никогда! Не используйте плагины для регистрации типов записей.

Момент, о котором я решил сразу упомянуть. Знаю, что не так давно я высказывал недовольство от того, что для работы с произвольными полями люди используют плагин ACF и рекомендовал всем перейти на Carbon Fields. Так вот, с типами записей всё ещё гораздо гораздо печальнее. Ведь вся суть в том, что такие плагины, как acf или carbon fields хотя бы помогают вам сэкономить время на разработку метабоксов (про acf кстати не уверен, по факту гораздо больше времени потратил, тыкаясь в его интерфейсе). Если кодить метабоксы с нуля, то там действительно немало кода. Так вот, а в случае с произвольными типами постов мне вообще неясен смысл использования плагинов. Самый популярный вроде CPT UI.

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

register_post_type()

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

add_action( 'init', 'true_register_post_type_init' );
 
function true_register_post_type_init() {
 
	$labels = array(
		'name' => 'Лиды',
		'singular_name' => 'Лид',
		'add_new' => 'Добавить лид',
		'add_new_item' => 'Добавить лид',
		'edit_item' => 'Редактировать лид',
		'new_item' => 'Новый лид',
		'all_items' => 'Все лиды',
		'search_items' => 'Искать лиды',
		'not_found' =>  'Лидов по заданным критериям не найдено.',
		'not_found_in_trash' => 'В корзине нет лидов.',
		'menu_name' => 'Лиды'
	);
 
	$args = array(
		'labels' => $labels,
		'public' => true,
		'publicly_queryable' => false,
		'has_archive' => false,
		'menu_icon' => 'dashicons-email-alt2',
		'menu_position' => 2,
		'supports' => array( 'title', 'editor' )
	);
 
	register_post_type( 'lead', $args );
}

Важно: в качестве имени типа поста (первый аргумент функции) нельзя использовать следующие слова: postpageattachmentrevisionnav_menu_itemactionordertheme. Помню случай, когда я пытался зарегистрировать тип поста order и не мог понять, почему ничего не работает.

Ещё более супер важно – если ваш тип записи будет просматриваемым на сайте и использовать ЧПУ, то обязательно после его создания зайдите в Настройки > Постоянные ссылки и, не меняя даже ничего, нажмите кнопку сохранения изменений.

Этот пример очень упрощён. На моем блоге вы также найдете полную документацию функции register_post_type() с подробным описанием её параметров и их значений.

В рамках работы с нашей темой вставляйте код в functions.php, а вообще читайте это.

В результате получаем:

Зарегистрировали тип записи WordPress

Круто, да? Дальше вы уже можете приступать к работе с этим типом записей, а я ещё покажу несколько моментов его настройки.

Тексты уведомлений для типа постов

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

Наверное вы понимаете, о каких уведомлениях идет речь. Это сообщения, которые появляются в верхней части экрана при например сохранении или обновлении поста.

Сообщение, появляющееся при обновлении поста данного типа поста

Если вы пропустите этот шаг, то по умолчанию будут использоваться уведомления из записей типа post.

add_filter( 'post_updated_messages', 'true_post_type_messages' );
 
function true_post_type_messages( $messages ) {
 
	global $post, $post_ID;
 
	$messages[ 'lead' ] = array( // lead - название созданного нами типа записей
		0 => '', // Данный индекс не используется.
		1 => 'Лид обновлён.',
		2 => 'Поле изменено.',
		3 => 'Поле удалено.',
		4 => 'Лид обновлён.',
		5 => isset( $_GET[ 'revision' ] ) ? sprintf( 'Лид восстановлен из редакции из редакции: %s', wp_post_revision_title( (int) $_GET[ 'revision' ], false ) ) : false,
		6 => 'Лид добавлен.',
		7 => 'Лид сохранён.',
		8 => 'Отправлено на проверку.',
		9 => sprintf( 'Лид запланирован на публикацию на <strong>%1$s</strong>.', date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ) ),
		10 => 'Черновик лида сохранён',
	);
 
	return $messages;
}

Кроме того, есть ещё сообщения быстрого редактирования постов. Вот о чём я говорю:

Изменяем сообщения массивого редактирования типа записей

Их тоже можно подкорректировать при помощи хуков, а конкретнее – при помощи bulk_post_updated_messages.

add_filter( 'bulk_post_updated_messages', 'true_bulk_post_updated_messages', 25, 2 );
 
function true_bulk_post_updated_messages( $messages, $counts ) {
 
	$bulk_messages[ 'lead' ] = array(
		// не совсем правильный способ, но уже полностью рабочий прямо сейчас
		'updated'   => $counts[ 'updated' ] . ' ' . true_wordform( $counts[ 'updated' ], 'лид', 'лида', 'лидов') . ' обновлено.',
		'locked'    => $counts[ 'locked' ] . ' ' . true_wordform( $counts[ 'locked' ], 'лид', 'лида', 'лидов') . ' не обновлено, потому что кто-то редактирует их.',
		'deleted'   => $counts[ 'deleted' ] . ' ' . true_wordform( $counts[ 'deleted' ], 'лид', 'лида', 'лидов') . ' удалено безвозвратно.',
		'trashed'   => $counts[ 'deleted' ] . ' ' . true_wordform( $counts[ 'deleted' ], 'лид', 'лида', 'лидов') . ' перемещено в корзину.',
		// правильный способ, это когда наш код поддерживает локализацию
		// но при написание чего-либо для себя, возможно в этом и нет большого смысла
		'untrashed' => _n( '%s lead restored from the Trash.', '%s leads restored from the Trash.', $bulk_counts[ 'untrashed' ] ),
	);
 
	return $bulk_messages;
 
}

Несколько важных моментов по коду сразу:

  • Функция true_wordform() вряд ли у вас определена, её вы можете найти тут и нужна она для склонения слов.
  • Однако это не совсем правильный способ, особенно, если вы пишете плагин или тему не для какого-то определённого клиента или для себя, а для людей. В таком случае ваш код должен поддерживать локализацию этих строк и использовать функцию _n().
  • $bulk_messages[ 'lead' ] – в качестве ключа этого массива указываем свой тип записи.

Вкладка «Помощь»

Вкладка «Помощь» находится в правой верхней части экрана. Для нашего типа поста её ещё пока что нет, но вы сможете найти её на странице записей в админке например.

вкладка Помощь в верхней правой части экрана

Да, содержимое этой вкладки мы тоже можем настроить. Это обычно бывает полезно при работе с клиентами, для которых админка WordPress нелегка в освоении. Туда можно добавить какую-нибудь справочную информацию и не только.

Что мы и сделаем:

добавление вкладки при помощи метода add_help_tab()

Следующий код будет работать в версиях WordPress 3.3 и выше.

add_action( 'admin_head', 'true_post_type_help_tab', 25 );
 
function true_post_type_help_tab() {
 
	$screen = get_current_screen();
 
	// Прекращаем выполнение функции, если находимся на страницах других типов постов
	if ( 'lead' !== $screen->post_type ) {
		return;
	}
 
	// Добавляем первую вкладку
	$screen->add_help_tab( array(
		'id'      => 'tab_1',
		'title'   => 'Общая информация',
		'content' => '<h3>Общая информация</h3><p>На этой странице вы сможете найти все заявки, отправленные через формы обрутной связи на странице контактов.</p>'
	) );
 
	// Добавляем вторую вкладку
	$screen->add_help_tab( array(
		'id'      => 'tab_2',
		'title'   => 'Вторая вкладка',
		'content' => '<h3>Вторая вкладка</h3><p>Содержимое второй вкладки</p>'
	) );
 
}

Колонки в таблице со списком постов произвольного типа

Про работу с колонками в админке у меня есть отдельный исчерпывающий урок. Сейчас же, в качестве примера, добавим ещё одну колонку, в которой будет выводиться текст сообщения лида.

Получится что-то в этом роде:

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

Код:

add_filter( 'manage_edit-lead_columns', 'true_add_lead_columns', 25 );
 
function true_add_lead_columns( $columns ){
 
	$message = array( 'message' => 'Сообщение' );
 	$columns = array_slice( $columns, 0, 2, true ) + $message + array_slice( $columns, 2, NULL, true );
 
	return $columns;
 
}
 
add_action( 'manage_posts_custom_column', 'true_fill_lead_columns', 25 );
 
function true_fill_lead_columns( $column ) {
 
	switch ( $column ) {
		case 'message': {
			global $post;
			echo wpautop( esc_html( $post->post_content ) );
			break;
		}
	}
 
}

На этом с регистрацией и настройкой типа записи – всё! Дальше уже работаем с ним в рамках нашей задачи, например в этом видео – автоматически будем создавать посты при отправке формы пользователями.

источник: учебник Михаила Радрастых

Пример плагина сотрудников.

добавляем тип записи и таксономия для него.

add_action( 'init', 'main' );

function main() {
    $taxLabels = [
        'name'              => 'Отделы',
        'singular_name'     => 'Отдел',
        'search_items'      => 'Поиск отделов',
        'all_items'         => 'Все отделы',
        'view_item '        => 'Просмотреть отдел',
        'parent_item'       => 'Родительский отдел',
        'parent_item_colon' => 'Родительский отдел:',
        'edit_item'         => 'Редактировать отдел',
        'update_item'       => 'Обновить отдел',
        'add_new_item'      => 'Добавить отдел',
        'new_item_name'     => 'Новый отдел',
        'menu_name'         => 'Отдел',
        'back_to_items'     => '← Вернуться к отделам',
    ];
    
    $taxArgs = [
        'public' => true,
        'labels' => $taxLabels,
        'hierarchical' => true,
    ];
    
	register_taxonomy('department', ['staff'], $taxArgs);
    
    
    $labels = array(
		'name' => 'Сотрудники',
		'singular_name' => 'Сотрудник',
		'add_new' => 'Добавить сотрудника',
		'add_new_item' => 'Добавить сотрудника',
		'edit_item' => 'Редактировать сотрудника',
		'new_item' => 'Новый сотрудник',
		'all_items' => 'Все Сотрудники',
		'search_items' => 'Искать Сотрудников',
		'not_found' =>  'Сотрудников по заданным критериям не найдено.',
		'not_found_in_trash' => 'В корзине нет сотрудников.',
		'menu_name' => 'Компания'
	);
 
	$args = array(
		'labels' => $labels,
		'public' => true,
		'has_archive' => true,
		'menu_icon' => 'dashicons-email-alt2',
		'menu_position' => 3,
		'supports' => array('title','editor','author','thumbnail','trackbacks','custom-fields','comments','revisions')
	);
 
	register_post_type('staff', $args);
}

Добавляем метаданные и метабокс для их редактирования

add_action( 'add_meta_boxes', 'staff_add_custom_box' );

function staff_add_custom_box() {
	$screens = [ 'staff' ];
	foreach ( $screens as $screen ) {
		add_meta_box(
			'staff_metabox',           // Unique ID
			'Карточка сотрудника',     // Box title
			'staff_custom_box_html',   // Content callback, must be of type callable
			$screen,                   // типы постов, для которых его подключим
            'normal', // расположение (normal, side, advanced)
            'high' // приоритет (default, low, high, core)
		);
	}
}

function staff_custom_box_html( $post ) {
    // сначала получаем значения этих полей
    $staff_phone = get_post_meta( $post->ID, 'phone', true );
    $staff_age = get_post_meta( $post->ID, 'age', true );
    wp_nonce_field( 'seopostsettingsupdate-' . $post->ID, '_truenonce' );
	?>
    <label for="phone_box">Телефон сотрудника</label>
    <input type="text" value="<?=esc_attr($staff_phone);?>" id="phone" name="phone" class="regular-text">
    
    <label for="age_box">Возраст сотрудника</label>
    <input type="number" value="<?=esc_attr($staff_age);?>" id="age" name="age" class="regular-text">
	<?php
}

пишем функцию для сохранения метаданных нового типа записи.

function true_save_meta_staff( $post_id, $post ) {
 
	// проверка одноразовых полей
	if ( ! isset( $_POST[ '_truenonce' ] ) || ! wp_verify_nonce( $_POST[ '_truenonce' ], 'seopostsettingsupdate-' . $post->ID ) ) {
		return $post_id;
	}
 
	// проверяем, может ли текущий юзер редактировать пост
	$post_type = get_post_type_object( $post->post_type );
 
	if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) {
		return $post_id;
	}
 
	// ничего не делаем для автосохранений
	if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
		return $post_id;
	}
 
	// проверяем тип записи
	if( !in_array($post->post_type, array('staff')) ) {
		return $post_id;
	}
 
	if( isset( $_POST[ 'phone' ] ) ) {
		update_post_meta( $post_id, 'phone', sanitize_text_field( $_POST[ 'phone' ] ) );
	} else {
		delete_post_meta( $post_id, 'phone' );
	}
	if( isset( $_POST[ 'age' ] ) ) {
		update_post_meta( $post_id, 'age', sanitize_text_field( $_POST[ 'age' ] ) );
	} else {
		delete_post_meta( $post_id, 'age' );
	}
 
	return $post_id;
}

Остаётся разработать шаблон для вывода этого типа постов. Либо написать в плагине шорткод выводящий эти записи и использовать его.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *