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

Уже несколько лет как WordPress закрепился среди основных систем управления контентом (CMS), но настоящим прорывом оказался механизм пользовательских типов сообщений. Давайте посмотрим, как это произошло и какие возможности у этого замечательного механизма.



Some of the custom post types you can create in WordPress.

Некоторые пользовательские типы сообщений которые вы можете создать в WordPress.

на что это похоже

На практике же, пользовательские типы сообщений существуют уже  в течении достаточно долгого времени, а именно с 17 февраля 2005 года, когда в WordPress 1.5 была добавлена ​​поддержка статических страниц, с появлением поля post_type в базе данных.

Функция wp_insert_post() впервые была добавлена в WordPress 1.0, поэтому, когда поле post_type было реализовано в версии 1.5, появилась возможность просто устанавливать значение post_type при вставке поста. Конечно, создание и управление пользовательскими типами постов требует гораздо большего, но с каждой новой версией все меньше и меньше приходиться писать код, так как функции WordPress становится все более и более гибкими.

Начиная с версии 2.8, функция register_post_type() и некоторые другие полезные штуковины появились в ночных сборках, а с выходом версии 2.9, эти функции стали доступны каждому. На данный момент, вам не нужно писать сотни строк кода, использовать хаки для того чтоб сделать WordPress полнофункциональной CMS. Вы можете использовать обширный список замечательных встроенных функций, чтобы заставить WordPress исполнять ваши приказы.

ЧТО сейчас wordpress может сделать для вас

Пользовательский тип поста это не более чем обычный пост с другим значением поля post_type  в базе данных. Тип обычного поста -  post, страницы — page, вложения — attachment и так далее. Вы можете создавать свои собственные типы, для определения типа созданного контента. Вы можете создавать пользовательские типы постов для книг, фильмов, рецензий, продуктов и так далее.

Если тип создан правильно, то при помощи нескольких строк кода, вы можете добиться следующего:

  • Пользовательский тип поста будут отображаться в админ-панели как отдельный пункт меню, со своим собственным списком постом и страницей добавления новой записи.
  • Переход по адресу http://mysite.com/customposttype/ приведет вас на страницу архива постов типа customposttype. Это напоминает посещение главной страницы для просмотра последних постов, относящихся к типу “post”.
  • Для пользовательских типов сообщений доступны категории и теги, или вы можете создать свою систему классификации.

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

Различные типы контента требуют различных данных. Для обычного поста, вы пожелаете задать автора, категорию, дату и так далее. Для пользовательского типа постов “книги”, в идеале вы хотели бы иметь возможность указать автора книги, количество страниц, жанр, издателя и другие специфичные для книг данные. Используя пользовательские мета боксы, это легко достижимо и также легко настраивается.

Пользовательские мета боксы позволяют добавлять дополнительные поля ввода на страницу редактирования поста. Обычно они используют пользовательские поля, так что вы могли бы пользоваться исключительно ими, но, выделяя некоторые пользовательские поля в качестве мета боксов, можно создать намного более гладкую и удобную для использования админ-панель.

Работа с пользовательскими типами постов

Для эффективного создания и использования пользовательских типов постов, вы должны знать как:

  • Создавать пользовательские типы постов,
  • Создавать пользовательские системы классификации,
  • Создавать пользовательские мета боксы.

Создание пользовательских типов сообщений

Первым пунктом нашей повестки дня является само создание типа поста. В идеале вы должны создать плагин во время работы с пользовательскими типами постов, но если вы не знаете как, или вам просто нужен быстрый тест, вы можете использовать файл functions.php  вашей темы.

function my_custom_post_product() {
	$args = array();
	register_post_type( 'product', $args );
}
add_action( 'init', 'my_custom_post_product' );

В своей простейшей форме, это приведет к созданию типа поста, который практически не имеет настроек. Он не будет публичным, он не появится в админ-панели, уведомления о результатах взаимодействия будут такими же, как и для обычных постов (например “ Пост сохранен, ” “Пост обновлен”) и так далее. Чтобы адаптировать наш новый тип поста к нашим потребностям, я пройдусь по наиболее часто используемым опциям и добавлю их в изначально пустой массив $args.

function my_custom_post_product() {
	$labels = array(
		'name'               => _x( 'Products', 'post type general name' ),
		'singular_name'      => _x( 'Product', 'post type singular name' ),
		'add_new'            => _x( 'Add New', 'book' ),
		'add_new_item'       => __( 'Add New Product' ),
		'edit_item'          => __( 'Edit Product' ),
		'new_item'           => __( 'New Product' ),
		'all_items'          => __( 'All Products' ),
		'view_item'          => __( 'View Product' ),
		'search_items'       => __( 'Search Products' ),
		'not_found'          => __( 'No products found' ),
		'not_found_in_trash' => __( 'No products found in the Trash' ),
		'parent_item_colon'  => '',
		'menu_name'          => 'Products'
	);
	$args = array(
		'labels'        => $labels,
		'description'   => 'Holds our products and product specific data',
		'public'        => true,
		'menu_position' => 5,
		'supports'      => array( 'title', 'editor', 'thumbnail', 'excerpt', 'comments' ),
		'has_archive'   => true,
	);
	register_post_type( 'product', $args );
}
add_action( 'init', 'my_custom_post_product' );
  • labels опция labels  должна содержать массив, определяющий различные метки, которые может иметь пользовательский тип поста. Я записал инициализацию массива отдельно, чтобы сделать аргументы, используемые для регистрации типа поста, более понятными.
  • description Краткое описание пользовательского типа поста, что он делает и зачем мы используем его.
  • public Эта опция одна контролирует кучу различных вещей. Задав для нее значение true, вы активируете множество других опций (все они связаны с видимостью). Например, можно сделать так, чтоб пользовательский тип поста был видим, но не доступен. Подробнее об этом позже.
  • menu_position Определяет позицию меню постов пользовательского типа в админ-панели. Установив цифру “5” в качестве опции, вы расположите его в 5 позициях ниже меню “Posts”. Чем больше используемое число, тем ниже расположение в меню.
  • supports Эта опция устанавливает стандартные элементы управления WordPress, которые доступны на странице редактирования поста пользовательского типа. По умолчанию, показаны только поля заголовка и редактора. Если вы хотите добавить поддержку комментариев, истории версий, формата постов и тому подобного вам следует указать их здесь. Для ознакомления с полным списком посмотрите в Кодексе секцию аргументов.
  • has_archive
    Если установить значение true, будут созданы правила для mod_rewrite, позволяющие получать доступ к архиву постов определенного типа по адресу http://mysite.com/posttype/ (например)

A custom post type in the menu.
Пользовательский тип постов в меню.

После установки этого, вы должны увидеть пункт меню для постов пользовательского типа. Вы должны иметь возможность добавлять сообщения, просматривать список постов в админ-панели, а также просматривать опубликованы посты на сайте.

Как я уже говорил, есть много вещей, которые вы можете изменить при создании типа поста. Я предлагаю посмотреть на список аргументов в Кодексе и ознакомиться с полным описанием каждой опции и значениями которые они могут принимать.

Пользовательские уведомления

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

function my_updated_messages( $messages ) {
	global $post, $post_ID;
	$messages['product'] = array(
		0 => '',
		1 => sprintf( __('Product updated. <a href="%s">View product</a>'), esc_url( get_permalink($post_ID) ) ),
		2 => __('Custom field updated.'),
		3 => __('Custom field deleted.'),
		4 => __('Product updated.'),
		5 => isset($_GET['revision']) ? sprintf( __('Product restored to revision from %s'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
		6 => sprintf( __('Product published. <a href="%s">View product</a>'), esc_url( get_permalink($post_ID) ) ),
		7 => __('Product saved.'),
		8 => sprintf( __('Product submitted. <a target="_blank" href="%s">Preview product</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
		9 => sprintf( __('Product scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview product</a>'), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
		10 => sprintf( __('Product draft updated. <a target="_blank" href="%s">Preview product</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
	);
	return $messages;
}
add_filter( 'post_updated_messages', 'my_updated_messages' );

Пользовательское сообщение после сохранения продукта.

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

Обратите внимание, что вы можете изменить сообщения для всех пользовательских типов постов с помощью одной этой функции. Массив $messages  содержит сообщения для всех типов постов, так что вы можете всех их изменить здесь. Я лично создаю функции для каждого типа поста, просто таким образом я легко могу сгруппировать создание типа поста и пользовательского сообщений вместе.

Контекстные подсказки

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

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

function my_contextual_help( $contextual_help, $screen_id, $screen ) {
	if ( 'product' == $screen->id ) {

		$contextual_help = '<h2>Products</h2>
		<p>Products show the details of the items that we sell on the website. You can see a list of them on this page in reverse chronological order - the latest one we added is first.</p>
		<p>You can view/edit the details of each product by clicking on its name, or you can perform bulk actions using the dropdown menu and selecting multiple items.</p>';

	} elseif ( 'edit-product' == $screen->id ) {

		$contextual_help = '<h2>Editing products</h2>
		<p>This page allows you to view/modify product details. Please make sure to fill out the available boxes with the appropriate details (product image, price, brand) and <strong>not</strong> add these details to the product description.</p>';

	}
	return $contextual_help;
}
add_action( 'contextual_help', 'my_contextual_help', 10, 3 );

Это немного сложно, потому что вы должны знать ID экрана на котором вы находитесь. Если вы посмотрите содержимое переменной $screen, вы легко определите ID. Эта функция также позволяет изменять контекстные подсказки всех пользовательских типов постов сразу, но я лично рекомендую группировать эту функцию месте с предыдущими двумя блоками и использовать для одного пользовательского типа поста за раз.

Обзор

Подведем итог, для создания “готового” пользовательского типа поста мы использовали три функции.  Чтоб создать сам пользовательский тип поста использовали функцию register_post_type() и две уловки — contextual_help и post_updated_messages для создания полезных подсказок и соответствующих уведомлений.

пользовательская система классификации

Обычные посты вашего блога используют категории и теги для создания организационной структуры. Тем не менее, та же организация, не обязательно имеет смысл для постов пользовательского типа. Записи в вашем блоге могут описывать вашу “Жизнь”, ваши “Мысли” или “Мечты”. Это, безусловно, не подходит для продуктов.

Это проблемы приводят разработчиков к созданию собственных организационых структур. Вы можете создать отдельную организационную структуру, называющуюся «Категории продуктов», которая будет главной для категорий, использующихся только для продуктов. Кевин Лири (Kevin Leary) написал замечательную статью о пользовательских системах классификации в WordPress, которую я очень рекомендую, здесь же я не буду сильно углубляться.

function my_taxonomies_product() {
	$args = array();
	register_taxonomy( 'product_category', 'product' $args );
}

add_action( 'init', 'my_taxonomies_product', 0 );

Как и пользовательские типы постов, вы можете легко и просто создать систему классификации, но нужно немного поработать над ней, чтобы адаптировать ее к вашим потребностям. Пользовательские системы классификации ведут себя немного лучше, поскольку они общедоступны по умолчанию, так что кода, записанного выше, вполне достаточно для адаптации организационной структуры под продукты. Давайте посмотрим более изощренный вариант.

function my_taxonomies_product() {
	$labels = array(
		'name'              => _x( 'Product Categories', 'taxonomy general name' ),
		'singular_name'     => _x( 'Product Category', 'taxonomy singular name' ),
		'search_items'      => __( 'Search Product Categories' ),
		'all_items'         => __( 'All Product Categories' ),
		'parent_item'       => __( 'Parent Product Category' ),
		'parent_item_colon' => __( 'Parent Product Category:' ),
		'edit_item'         => __( 'Edit Product Category' ),
		'update_item'       => __( 'Update Product Category' ),
		'add_new_item'      => __( 'Add New Product Category' ),
		'new_item_name'     => __( 'New Product Category' ),
		'menu_name'         => __( 'Product Categories' ),
	);
	$args = array(
		'labels' => $labels,
		'hierarchical' => true,
	);
	register_taxonomy( 'product_category', 'product', $args );
}
add_action( 'init', 'my_taxonomies_product', 0 );

Как видите, не многое изменилось. Мы добавили несколько меток и разрешили иерархическую вложенность. Это позволяет создавать организационные структуры наподобие категорий. Если для опции, определяющей возможность использования иерархической вложенности, оставить значение по-умолчанию (false), то ваша организационная структура будет представлена стандартными тегами.

Есть несколько других мощных опций, о которых вы можете прочитать в статье Лири, или вы можете найти в Кодексе информацию о register_taxonomy() .

The Product Categories custom taxonomy.
Пользовательская организационная структура “Product Categories”.

мета боксы постов

Мета  боксы это перетаскиваемые боксы, которые вы видите на экране редактирования поста в WordPress. Есть множество встроенных в мета боксов, таких как контроль публикации, классификаторы, бокс автора и т.д., но вы можете создать нужные вам боксы самостоятельно.

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

Джастин Тэдлок написал всеобъемлющую статью о пользовательских мета боксах для  Smashing Magazine, которая является отличной углубленной статьей на эту тему. Я советую вам прочитать её, для того чтоб иметь полное представление, а начнем мы здесь.

Создание мета бокса требует трех шагов:

  • Определить сам бокса,
  • Определить содержания мета бокса,
  • Определить как обрабатывать данные из бокса.

Определение Мета Бокса

add_action( 'add_meta_boxes', 'product_price_box' );
function product_price_box() {
    add_meta_box(
        'product_price_box',
        __( 'Product Price', 'myplugin_textdomain' ),
        'product_price_box_content',
        'product',
        'side',
        'high'
    );
}

Приведенный выше код создает мета бокс со следующими параметрами (в указанном порядке):

  • Уникальный идентификатор мета бокса (не обязательно должен совпадать с именем функции),
  • Название мета бокса (видимо для пользователей),
  • Функция, которая будет отображать содержимое бокса,
  • Тип поста к которому относиться мета бокс,
  • Размещение мета бокса,
  • Приоритет мета бокса (определяет “как высоко” он находится).

Определение содержания мета бокса

function product_price_box_content( $post ) {
	wp_nonce_field( plugin_basename( __FILE__ ), 'product_price_box_content_nonce' );
	echo '';
	echo '
';
}

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

Обработка данных

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

add_action( 'save_post', 'product_price_box_save' );
function product_price_box_save( $post_id ) {

	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
	return;

	if ( !wp_verify_nonce( $_POST['product_price_box_content_nonce'], plugin_basename( __FILE__ ) ) )
	return;

	if ( 'page' == $_POST['post_type'] ) {
		if ( !current_user_can( 'edit_page', $post_id ) )
		return;
	} else {
		if ( !current_user_can( 'edit_post', $post_id ) )
		return;
	}
	$product_price = $_POST['product_price'];
	update_post_meta( $post_id, 'product_price', $product_price );
}

Большая часть кода этой функции связана с безопасностьюПрежде всего, если осуществляется автосохранение, ничего не произойдет, потому что пользователь фактически не подтвердил ввод. Затем проверяются данные, введенные в одноразовое поле и права пользователя. Если все предыдущие проверки пройдены успешно, мы берем наши данные и добавляем к сообщен …

Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров

Comments are closed.