WordPress как на ладони
wordpress jino

register_post_type() WP 2.9

Создает новый тип записи или изменяет имеющийся.

Тип записи должен создаваться в момент хука-события init. Он не будет создан, если прикрепить функцию до init и может работать неправильно, если использовать после.

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

С версии 4.6 был создан новый класс WP_Post_Type и весь код функции теперь обрабатывается этим классом, а эта функция стала оберткой для него.

Таксономии

Если для нового типа записи регистрируется таксономия, то всегда регистрируйте эту таксономию при регистрации типа записи, для этого используя параметр taxonomies. Если вы этого не сделаете, тип поста и таксономии не будут опознаны как связанные при срабатывании хуков, таких как: parse_query или pre_get_posts. Это может привести к неожиданным последствиям и ошибкам.

Таксономии нужно регистрировать отдельно. Т.е. несмотря на то, что вы указали таксономии при регистрации нового типа записи, вы должны отдельно зарегистрировать эти таксономии используя register_taxonomy().

Зарезервированные типы постов

Нельзя использовать следующие названия для новых типов постов, так как они используются WordPress:

  • post, page, attachment, revision, nav_menu_item — типы постов WordPress;
  • action, order, theme — названия, которые используются в функциях WordPress.

Во избежании конфликтов с уже используемыми типами постов рекомендуется использовать префикс в названии нового типа поста или указывать уникальную строку.

Хуки из функции:
Возвращает

WP_Post_Type объект (с версии 4.6).

Использование

register_post_type( $post_type, $args );

Важно: после создания нового типа записи. Обязательно нужно зайти в «Настройки» > «Постоянные ссылки» и просто нажать там кнопку «Сохранить изменения». Нужно это для того, чтобы правила ЧПУ были пересозданы и туда были добавлены правила нового типа записи.

Шаблон для создания нового типа записи

add_action('init', 'register_post_types');
function register_post_types(){
	register_post_type('post_type_name', array(
		'label'  => null,
		'labels' => array(
			'name'               => '____', // основное название для типа записи
			'singular_name'      => '____', // название для одной записи этого типа
			'add_new'            => 'Добавить ____', // для добавления новой записи
			'add_new_item'       => 'Добавление ____', // заголовка у вновь создаваемой записи в админ-панели.
			'edit_item'          => 'Редактирование ____', // для редактирования типа записи
			'new_item'           => 'Новое ____', // текст новой записи
			'view_item'          => 'Смотреть ____', // для просмотра записи этого типа.
			'search_items'       => 'Искать ____', // для поиска по этим типам записи
			'not_found'          => 'Не найдено', // если в результате поиска ничего не было найдено
			'not_found_in_trash' => 'Не найдено в корзине', // если не было найдено в корзине
			'parent_item_colon'  => '', // для родителей (у древовидных типов)
			'menu_name'          => '____', // название меню
		),
		'description'         => '',
		'public'              => false,
		'publicly_queryable'  => null,
		'exclude_from_search' => null,
		'show_ui'             => null,
		'show_in_menu'        => null, // показывать ли в меню адмнки
		'show_in_admin_bar'   => null, // по умолчанию значение show_in_menu
		'show_in_nav_menus'   => null,
		'show_in_rest'        => null, // добавить в REST API. C WP 4.7
		'rest_base'           => null, // $post_type. C WP 4.7
		'menu_position'       => null,
		'menu_icon'           => null, 
		//'capability_type'   => 'post',
		//'capabilities'      => 'post', // массив дополнительных прав для этого типа записи
		//'map_meta_cap'      => null, // Ставим true чтобы включить дефолтный обработчик специальных прав
		'hierarchical'        => false,
		'supports'            => array('title','editor'), // 'title','editor','author','thumbnail','excerpt','trackbacks','custom-fields','comments','revisions','page-attributes','post-formats'
		'taxonomies'          => array(),
		'has_archive'         => false,
		'rewrite'             => true,
		'query_var'           => true,
	) );
}
$post_type(строка) (обязательный)
Название типа записи (максимум 20 символов). Может содержать только строчные символы, числа, _ или -: a-z0-9_-.
По умолчанию: нет
$args(массив)
Массив аргументов.
По умолчанию: нет

Аргументы параметра $args

label(строка)
Имя типа записи помеченное для перевода на другой язык.
По умолчанию: $post_type
labels(массив)

Массив содержащий в себе названия ярлыков для типа записи.

Для нового типа записи, если для неустановленных строк, будут использованы названия (ярлыки) "постов" у не древовидных типов и ярлыки "постоянных страниц" древовидных типов. См. get_post_type_labels()

В массиве можно указать следующие аргументы:

'name' => '',
// основное название для типа записи, обычно во множественном числе.
'singular_name' => '',
// название для одной записи этого типа.
'add_new' => '',
// текст для добавления новой записи, как "добавить новый" у постов в админ-панели. Если нужно использовать перевод названия, вписывайте подобным образом: _x('Add New', 'product');
'add_new_item' => '',
// текст заголовка у вновь создаваемой записи в админ-панели. Как "Добавить новый пост" у постов.
'edit_item' => '',
// текст для редактирования типа записи. По умолчанию: редактировать пост/редактировать страницу.
'new_item' => '',
// текст новой записи. По умолчанию: "Новый пост"
'view_item' => '',
// текст для просмотра записи этого типа. По умолчанию: "Посмотреть пост"/"Посмотреть страницу".
'search_items' => '',
// текст для поиска по этим типам записи. По умолчанию "Найти пост"/"найти страницу".
'not_found' => '',
// текст, если в результате поиска ничего не было найдено. По умолчанию: "Постов не было найдено"/"Страниц не было найдено".
'not_found_in_trash' => '',
// текст, если не было найдено в корзине. По умолчанию "Постов не было найдено в корзине"/"Страниц не было найдено в корзине".
'parent_item_colon' => '',
// текст для родительских типов. Этот параметр не используется для не древовидных типов записей. По умолчанию "Родительская страница".
'all_items' => '',
// Все записи. По умолчанию равен menu_name
'archives' => '',
// Архивы записей. По умолчанию равен all_items
'insert_into_item' => '',
// Вставить в запись
'uploaded_to_this_item' => '',
// Загружено для этой записи
'featured_image' => '',
// Миниатюра записи
'set_featured_image' => '',
// Установить миниатюру записи
'remove_featured_image' => '',
// Удалить миниатюру записи
'use_featured_image' => '',
// Использовать как миниатюру записи
'filter_items_list' => '',
// Фильтровать список записей
'items_list_navigation' => '',
// Навигация по записям
'items_list' => '',
// Список записей
'menu_name' => '',
// Название меню. По умолчанию равен name.
'name_admin_bar' => '',
// Название в админ баре (тулбаре). По умолчанию равен singular_name.
'view_items' => '',
// Название в тулбаре, для страницы архива типа записей. По умолчанию: «View Posts» / «View Pages». С WP 4.7.
'attributes' => '',
// Название для метабокса атрибутов записи (у страниц это метабокс «Свойства страницы» - «Page Attributes»). По умолчанию: «Post Attributes» или «Page Attributes». С WP 4.7.

По умолчанию: если не установлено, name и singular_name примят значение аргумента label

description(строка)
Короткое описание этого типа записи.
По умолчанию: ''
public(логический)

Определяет является ли тип записи публичным или нет. На основе этого параметра строятся много других, т.е. это своего рода пред-установка для следующих параметров:

  • false

    • show_ui = false - не показывать пользовательский интерфейс (UI) для этого типа записей
    • publicly_queryable = false - запросы относящиеся к этому типу записей не будут работать в шаблоне
    • exclude_from_search = true - этот тип записей не будет учитываться при поиске по сайту
    • show_in_nav_menus = false - этот тип записей будет спрятан из выбора меню навигации
  • true
    • show_ui = true
    • publicly_queryable = true
    • exclude_from_search = false
    • show_in_nav_menus = true

По умолчанию: false

publicly_queryable(логический)
Запросы относящиеся к этому типу записей будут работать во фронтэнде (в шаблоне сайта).
По умолчанию: значение глобального аргумента (public)
exclude_from_search(логический)

Исключить ли этот тип записей из поиска по сайту. 1 (true) - да, 0 (false) - нет.

Если этот параметр установлен в true, то для терминов таксономий привязанных к этому типу записей, вывод работать не будет (пусть даже параметр public равен true). Т.е. этот тип постов будет полностью исключен из запросов типа query_posts()!

По умолчанию: обратное значение аргумента public

show_ui(логический)

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

Так, например, если указать true, а в show_in_menu = false. То у нас будет возможность зайти на страницу управления типом записи, т.е. движок будет понимать и обрабатывать такие запросы, но ссылки на эту страницу в меню не будет ...

По умолчанию: значение аргумента public

show_in_menu(строка/логический)

Показывать ли тип записи в администраторском меню и где именно показывать управление типом записи. Аргумент show_ui должен быть включен!

  • false - не показывать в администраторском меню.
  • true - показывать как меню первого уровня.
  • строка - показывать как под-меню меню первого уровня, например, подменю для 'tools.php' или 'edit.php?post_type=page' для произвольных типов меню нужно указывать $menu_slug см. add_menu_page().

ЗАМЕТКА: Если используется строка для того, чтобы показать как подменю, какого-нибудь главного меню, создаваемого плагином, этот пункт станет первым в списке и соответственно изменит расположение пунктов меню. Для того, чтобы этого не произошло, в плагине, который создает свое меню нужно установить приоритет для действия admin_menu 9 или ниже.

По умолчанию: null

show_in_admin_bar(логический)
Сделать этот тип доступным из админ бара.
По умолчанию: null (значение $show_in_menu)
show_in_nav_menus(логический)
Включить возможность выбирать этот тип записи в меню навигации.
По умолчанию: значение глобального аргумента
show_in_rest(логический)
Нужно ли включать тип записи в REST API. С WP 4.7.
rest_base(строка)
Ярлык в REST API. По умолчанию, название типа записи. С WP 4.7.
По умолчанию: $post_type
rest_controller_class(строка)
Название класса контроллера в REST API. С WP 4.7.
По умолчанию: 'WP_REST_Terms_Controller'
menu_position(число)

Позиция где должно расположится меню нового типа записи:

  • 1 — в самом верху меню
  • 2-3 — под «Консоль»
  • 4-9 — под «Записи»
  • 10-14 — под «Медиафайлы»
  • 15-19 — под «Ссылки»
  • 20-24 — под «Страницы»
  • 25-59 — под «Комментарии» (по умолчанию, null)
  • 60-64 — под «Внешний вид»
  • 65-69 — под «Плагины»
  • 70-74 — под «Пользователи»
  • 75-79 — под «Инструменты»
  • 80-99 — под «Параметры»
  • 100+ — под разделителем после «Параметры»

По умолчанию: null

menu_icon(строка)
Ссылка на картинку, которая будет использоваться для этого меню.
С выходом WordPress 3.8 появился новый пакет иконок Dashicons, который входит в состав ядра WordPress. Это комплект из более 150 векторных изображений. Чтобы установит одну из иконок, напишите её название в этот параметр. Например иконка постов, называется так: dashicons-admin-post, а ссылок dashicons-admin-links.
По умолчанию: null - иконка как у меню постов
capability_type(строка/массив)

Строка которая будет маркером для установки прав для этого типа записи.
Встроенные маркеры это: post и page.

Можно передавать массив, где первое значение будет использоваться для единственного числа, а второе для множественного, например: array('story', 'stories'). Если передается строка, то для множественного числа просто прибавляется 's' на конце.

capability_type используется для построения списка прав, которые будут записаны в параметр 'capabilities'.

При установке нестандартного маркера (не post или page), параметр map_meta_cap можно установить в true или в false:

  • Если поставить true — то WordPress автоматически сгенерирует группу прав для параметра 'capabilities' на основе введенных здесь данных. При этом указанные в параметре 'capabilities' права дополнят имеющийся список прав.
  • Если установить false — то WordPress ничего генерировать не будет и вам придется самому полностью прописать все возможные права для этого типа записи в параметре 'capabilities'.

По умолчанию: "post"

Пример: допустим мы указали тут строку bill что равносильно array('bill', 'bills'), тогда WordPress автоматически сгенерирует следующие права для параметра 'capabilities':

[cap] => stdClass Object
	(
		[edit_post] => edit_bill
		[read_post] => read_bill
		[delete_post] => delete_bill
		[edit_posts] => edit_bills
		[edit_others_posts] => edit_others_bills
		[publish_posts] => publish_bills
		[read_private_posts] => read_private_bills
		[read] => read
		[delete_posts] => delete_bills
		[delete_private_posts] => delete_private_bills
		[delete_published_posts] => delete_published_bills
		[delete_others_posts] => delete_others_bills
		[edit_private_posts] => edit_private_bills
		[edit_published_posts] => edit_published_bills
		[create_posts] => edit_bills
	)

Чтобы посмотреть какие права были созданы, загляните в глобальную переменную: $GLOBALS['wp_post_types']['bill'].

capabilities(массив)

Массив прав для этого типа записи.

По умолчанию, доступны 8 элементов массива, которые определяют права для этого типа записей (даже если map_meta_cap = false), это:

  • edit_post, read_post и delete_post - 3 разрешения контролирующие редактирование, прочтение и удаление типа записи. Это мета-права: не примитивные права, которые требуют вычислений на лету. Они не записываются в список прав каждого пользователя, а превращаются в примитивные права на лету с помощью функции map_meta_cap().
  • create_posts - алиас: тоже самое что и право edit_posts.
  • edit_posts - контролирует возможность редактировать объекты этого типа записи.
  • edit_others_posts - контролирует возможность редактировать объекты этого типа записей, которые принадлежат другому пользователю. Если тип записи не поддерживает авторов, то поведение этого аргумента будет похоже на edit_posts.
  • publish_posts - контролирует публикацию объектов этого типа записи.
  • read_private_posts - контролирует возможность прочтения личных объектов (записей).

Заметка: примитивные права фида *_posts используются в движке в разных местах.

Существуют еще 8 примитивных прав, которые не относятся напрямую к ядру. Но относятся к функции map_meta_cap() и проверяются там. Они устанавливаются автоматически, если указан параметр map_meta_cap = true:

  • read - разрешает просматривать объект во фронт-энде.
  • delete_posts - разрешает удалять объект этого типа записи.
  • delete_private_posts - разрешает удалять личный объект этого типа записи.
  • delete_published_posts - разрешает удалять опубликованные объекты этого типа записи.
  • delete_others_posts - разрешает удалять записи принадлежащие другим автора. Если у записи нет автора, то поведение передается delete_posts.
  • edit_private_posts - разрешает редактировать личные записи.
  • edit_published_posts - разрешает редактировать опубликованные записи.
  • create_posts - разрешает создавать новые записи.

Заметка: Чтобы пользователь мог создавать новые записи, его роль должна кроме прочего иметь право 'edit_posts'.

Этот capabilities параметр обычно устанавливается автоматически, опираясь на 'capability_type'. Например если установить 'capability_type' и 'map_meta_cap' и посмотреть в переменную $GLOBALS['wp_post_types']['post_type'], то мы увидим такой объект:

[cap] => stdClass Object
(
	// Мета возможности
	[edit_post]   => "edit_{$capability_type}"
	[read_post]   => "read_{$capability_type}"
	[delete_post] => "delete_{$capability_type}"

	// Примитивные права используются за пределами map_meta_cap():
	[edit_posts]         => "edit_{$capability_type}s"
	[edit_others_posts]  => "edit_others_{$capability_type}s"
	[publish_posts]      => "publish_{$capability_type}s"
	[read_private_posts] => "read_private_{$capability_type}s"

	// Примитивные права используются в map_meta_cap():
	[read]                   => "read",
	[delete_posts]           => "delete_{$capability_type}s"
	[delete_private_posts]   => "delete_private_{$capability_type}s"
	[delete_published_posts] => "delete_published_{$capability_type}s"
	[delete_others_posts]    => "delete_others_{$capability_type}s"
	[edit_private_posts]     => "edit_private_{$capability_type}s"
	[edit_published_posts]   => "edit_published_{$capability_type}s"
	[create_posts]           => "edit_{$capability_type}s"
)

где, s - это множественное число.

По умолчанию: используется аргумент capability_type для построения списка разрешений

map_meta_cap(логический)

Ставим true, чтобы включить дефолтный обработчик специальных прав map_meta_cap(). Он преобразует неоднозначные права (edit_post - один пользователь может, а другой нет) в примитивные (edit_posts - все пользователи могут). Обычно для типов постов этот параметр нужно включать, если типу поста устанавливаются особые права (отличные от 'post').

Заметка: если установить в false, то стандартная роль "Администратор" не сможет редактировать этот тип записи. Для снятия такого ограничения придется добавить право 'edit_{post_type}s' к роли администратор.

По умолчанию: false

hierarchical(логический)

Будут ли записи этого типа иметь древовидную структуру (как постоянные страницы).

true - да, будут древовидными
false - нет, будут связаны с таксономией (категориями)

По умолчанию: false

supports(массив)

Вспомогательные поля на странице создания/редактирования этого типа записи. Метки для вызова функции add_post_type_support().

  • title - блок заголовка;
  • editor - блок для ввода контента;
  • author - блог выбора автора;
  • thumbnail блок выбора миниатюры записи. Нужно также включить поддержку в установке темы post-thumbnails;
  • excerpt - блок ввода цитаты;
  • trackbacks - блок уведомлений;
  • custom-fields - блок установки произвольных полей;
  • comments - блок комментариев;
  • revisions - блок ревизий (не отображается пока нет ревизий);
  • page-attributes - блок атрибутов постоянных страниц (шаблон и древовидная связь записей, древовидность должна быть включена).
  • post-formats – блок форматов записи, если они включены в теме.

По умолчанию: array('title','editor')

register_meta_box_cb(строка)
callback функция, которая будет срабатывать при установки мета блоков для страницы создания/редактирования этого типа записи. Используйте remove_meta_box() и add_meta_box() в callback функции.
По умолчанию: нет
taxonomies(массив)

Массив зарегистрированных таксономий, которые будут связанны с этим типом записей, например: category или post_tag.

Связать таксономии с записью можно позднее через функцию register_taxonomy_for_object_type().

Таксономии нужно регистрировать с помощью функции register_taxonomy().

По умолчанию: нет

permalink_epmask(строка)

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

  • EP_NONE
  • EP_PERMALINK
  • EP_ATTACHMENT
  • EP_DATE
  • EP_YEAR
  • EP_MONTH
  • EP_DAY
  • EP_ROOT
  • EP_COMMENTS
  • EP_SEARCH
  • EP_CATEGORIES
  • EP_TAGS
  • EP_AUTHORS
  • EP_PAGES
  • EP_ALL

Конечная точка - это то что добавляется в конец URL, например /trackback/. Конечные точки прикрепляются к типу записи (добавляются в правила перезаписи) с помощью функции add_rewrite_endpoint().

Этот параметр позволяет указать, какую группу конечных точек мы хотим подключить к создаваемому типу записи (к URL записи). Например, если указать 'permalink_epmask' = EP_PAGES & EP_TAGS, то наш тип записи будет иметь все конечные точки, которые предусмотрены для постоянных страниц и меток.

По умолчанию permalink_epmask = EP_PERMALINK - это означает, что в URL создаваемого типа записи (в правила ЧПУ) будут добавлены конечные точки, которые добавляются к обычным записям WordPress.

Если не нужно добавлять никаких конечных точек к новому типу записи, то нужно указать EP_NONE. Или указываем EP_ALL, когда нужно добавить все конечные точки.

По умолчанию: EP_PERMALINK

has_archive(строка/логический)

Включить поддержку страниц архивов для этого типа записей (пр. УРЛ записи выглядит так: site.ru/type/post_name, тогда УРЛ архива будет такой: site.ru/type.

Если указать строку, то она будет использована в ЧПУ. Например, укажем тут typepage и получим ссылку на архив типа записи такого вида: site.ru/typepage
Файл этого архива в теме будет иметь вид archive-type.php). Для архивов будет добавлено новое правило ЧПУ, если аргумент rewrite включен.
По умолчанию: false

rewrite(массив/логический)

Использовать ли ЧПУ для этого типа записи. Чтобы не использовать ЧПУ укажите false. По умолчанию: true — название типа записи используется как префикс в ссылке. Можно в массиве указать дополнительные параметры для построения ЧПУ:

  • slug (строка)
    Префикс в ЧПУ (/префикс/ярлык_записи). Используйте array( 'slug' => $slug ), чтобы создать другой префикс.
    В этом параметре можно указывать плейсхолдеры типа %category%. Но их нужно создать с помощью add_rewrite_tag() и научить WP их понимать.
    По умолчанию: название типа записи

  • with_front (логический)
    Нужно ли в начало вставлять общий префикс из настроек. Префикс берется из $wp_rewite->front. Например, если структура постоянных ссылок записей в настройках имеет вид blog/%postname%, то при false получим: /news/название_поста, а при true получим: /blog/news/название_поста.
    По умолчанию: true

  • feeds (логический)
    Добавить ли правило ЧПУ для RSS ленты этого типа записи.
    По умолчанию: значение аргумента has_archive

  • pages (логический)
    Добавить ли правило ЧПУ для пагинации архива записей этого типа. Пр: /post_type/page/2.
    По умолчанию: true

По умолчанию: true (тип записи используется как префикс)

query_var(строка/логический)
Ставим false, чтобы убрать возможность запросов или устанавливаем название запроса для этого типа записей.
По умолчанию: true - устанавливается аргумент $post_type
can_export(логический)
Возможность экспорта этого типа записей.
По умолчанию: true
delete_with_user(логический)

true - удалять записи этого типа принадлежащие пользователю при удалении пользователя. Если включена корзина, записи не удаляться, а поместятся в корзину.
false - при удалении пользователя его записи этого типа никак не будут обрабатываться.
null - записи удаляться или будут перемещены в корзину, если post_type_supports('author') установлена. И не обработаются, если поддержки 'author' у типа записи нет.

По умолчанию: null

_builtin(логический)
Для внутреннего использования! True, если это встроенный/внутренний типа записи.
По умолчанию: false
_edit_link(строка)
Для внутреннего использования! Часть URL в ссылке на редактирования этого типа записи.
По умолчанию: 'post.php?post=%d'

Примеры

#1 Регистрация нового типа записи

Пример регистрации произвольного типа записей "book". Также в примере показано как включить сообщения при обновлении и поддержку раздела помощь.

add_action('init', 'my_custom_init');
function my_custom_init(){
	register_post_type('book', array(
		'labels'             => array(
			'name'               => 'Книги', // Основное название типа записи
			'singular_name'      => 'Книга', // отдельное название записи типа Book
			'add_new'            => 'Добавить новую',
			'add_new_item'       => 'Добавить новую книгу',
			'edit_item'          => 'Редактировать книгу',
			'new_item'           => 'Новая книга',
			'view_item'          => 'Посмотреть книгу',
			'search_items'       => 'Найти книгу',
			'not_found'          =>  'Книг не найдено',
			'not_found_in_trash' => 'В корзине книг не найдено',
			'parent_item_colon'  => '',
			'menu_name'          => 'Книги'

		  ),
		'public'             => true,
		'publicly_queryable' => true,
		'show_ui'            => true,
		'show_in_menu'       => true,
		'query_var'          => true,
		'rewrite'            => true,
		'capability_type'    => 'post',
		'has_archive'        => true,
		'hierarchical'       => false,
		'menu_position'      => null,
		'supports'           => array('title','editor','author','thumbnail','excerpt','comments')
	) );
}

Сообщения при публикации или изменении типа записи book:

// Сообщения при публикации или изменении типа записи book
add_filter('post_updated_messages', 'book_updated_messages');
function book_updated_messages( $messages ) {
	global $post;

	$messages['book'] = array(
		0 => '', // Не используется. Сообщения используются с индекса 1.
		1 => sprintf( 'Book обновлено. <a href="%s">Посмотреть запись book</a>', esc_url( get_permalink($post->ID) ) ),
		2 => 'Произвольное поле обновлено.',
		3 => 'Произвольное поле удалено.',
		4 => 'Запись Book обновлена.',
		/* %s: дата и время ревизии */
		5 => isset($_GET['revision']) ? sprintf( 'Запись Book восстановлена из ревизии %s', wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
		6 => sprintf( 'Запись Book опубликована. <a href="%s">Перейти к записи book</a>', esc_url( get_permalink($post->ID) ) ),
		7 => 'Запись Book сохранена.',
		8 => sprintf( 'Запись Book сохранена. <a target="_blank" href="%s">Предпросмотр записи book</a>', esc_url( add_query_arg( 'preview', 'true', get_permalink($post->ID) ) ) ),
		9 => sprintf( 'Запись Book запланирована на: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Предпросмотр записи book</a>',
		  // Как форматировать даты в PHP можно посмотреть тут: http://php.net/date
		  date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
		10 => sprintf( 'Черновик записи Book обновлен. <a target="_blank" href="%s">Предпросмотр записи book</a>', esc_url( add_query_arg( 'preview', 'true', get_permalink($post->ID) ) ) ),
	);

	return $messages;
}

Раздел "помощь" типа записи book:

// Раздел "помощь" типа записи book
add_action( 'contextual_help', 'add_help_text', 10, 3 );
function add_help_text( $contextual_help, $screen_id, $screen ){
	//$contextual_help .= print_r($screen); // используйте чтобы помочь определить параметр $screen->id
	if('book' == $screen->id ) {
		$contextual_help = '
		<p>Напоминалка при редактировании записи book:</p>
		<ul>
			<li>Указать жанр, например Фантастика или История.</li>
			<li>Указать автора книги.</li>
		</ul>
		<p>Если нужно запланировать публикацию на будущее:</p>
		<ul>
			<li>В блоке с кнопкой "опубликовать" нажмите редактировать дату.</li>
			<li>Измените дату на нужную, будущую и подтвердите изменения кнопкой ниже "ОК".</li>
		</ul>
		<p><strong>За дополнительной информацией обращайтесь:</strong></p>
		<p><a href="/" target="_blank">Блог о WordPress</a></p>
		<p><a href="http://wordpress.org/support/" target="_blank">Форум поддержки</a></p>
		';
	}
	elseif( 'edit-book' == $screen->id ) {
		$contextual_help = '<p>Это раздел помощи показанный для типа записи Book и т.д. и т.п.</p>';
	}

	return $contextual_help;
}

#2 Добавление элемента таксономии в ЧПУ

Для нового типа записи можно указать разные ЧПУ с помощью параметра rewrite. Этот пример показывает, как добавить в ЧПУ нового типа записи таксономию.

Допустим, мы регистрируем типа записи catalog и таксономию products для него. Далее, нам нужно чтобы при публикации записи и выборе для нее элемента таксономии. Этот элемент добавлялся в ЧПУ и в результате ссылка на тип записи выглядела так:
http://site.ru/post_type_name/taxonomy_term_name/post_name.

Для этого нужно указать аргумент slug в параметре rewrite при регистрации типа записи:

'rewrite' => array( 'slug'=>'catalog/%products%', 'with_front' => false ),
'has_archive' => 'catalog', // если нужна страница архива тут указываем её ярлык а не true

Теперь нужно добавить хук, чтобы заменять %products% при получении ссылки на запись через функцию get_permalink() и производные от нее функции:

## Отфильтруем ЧПУ произвольного типа
// сам фильтр: apply_filters( 'post_type_link', $post_link, $post, $leavename, $sample );
add_filter('post_type_link', 'products_permalink', 1, 2);

function products_permalink( $permalink, $post ){
	// выходим если это не наш тип записи: без холдера %products%
	if( strpos($permalink, '%products%') === FALSE )
		return $permalink;

	// Получаем элементы таксы
	$terms = get_the_terms($post, 'products');
	// если есть элемент заменим холдер
	if( ! is_wp_error($terms) && !empty($terms) && is_object($terms[0]) )
		$taxonomy_slug = $terms[0]->slug;
	// элемента нет, а должен быть...
	else
		$taxonomy_slug = 'no-products';

	return str_replace('%products%', $taxonomy_slug, $permalink );
}

В результате ЧПУ записи будет как указано выше и ссылка будет распознаваться правилами перезаписи WordPress.

#3 Добавление таксономии в ЧПУ

Этот пример показывает как создать запись типа Вопросы и разделы для нее. При этом ЧПУ будут:

  • У записи: site.ru/faq/{категория}/{ярлык-записи}
  • У таксы: site.ru/faq/{категория}
add_action( 'init', 'register_faq_post_type' );
function register_faq_post_type() {
	// Раздел вопроса - faqcat
	register_taxonomy('faqcat', array('faq'), array(
		'label'                 => 'Раздел вопроса', // определяется параметром $labels->name
		'labels'                => array(
			'name'              => 'Разделы вопросов',
			'singular_name'     => 'Раздел вопроса',
			'search_items'      => 'Искать Раздел вопроса',
			'all_items'         => 'Все Разделы вопросов',
			'parent_item'       => 'Родит. раздел вопроса',
			'parent_item_colon' => 'Родит. раздел вопроса:',
			'edit_item'         => 'Ред. Раздел вопроса',
			'update_item'       => 'Обновить Раздел вопроса',
			'add_new_item'      => 'Добавить Раздел вопроса',
			'new_item_name'     => 'Новый Раздел вопроса',
			'menu_name'         => 'Раздел вопроса',
		),
		'description'           => 'Рубрики для раздела вопросов', // описание таксономии
		'public'                => true,
		'show_in_nav_menus'     => false, // равен аргументу public
		'show_ui'               => true, // равен аргументу public
		'show_tagcloud'         => false, // равен аргументу show_ui
		'hierarchical'          => true,
		'rewrite'               => array('slug'=>'faq', 'hierarchical'=>false, 'with_front'=>false, 'feed'=>false ),
		'show_admin_column'     => true, // Позволить или нет авто-создание колонки таксономии в таблице ассоциированного типа записи. (с версии 3.5)
	) );

	// тип записи - вопросы - faq
	register_post_type('faq', array(
		'label'               => 'Вопросы',
		'labels'              => array(
			'name'          => 'Вопросы',
			'singular_name' => 'Вопрос',
			'menu_name'     => 'Архив вопросов',
			'all_items'     => 'Все вопросы',
			'add_new'       => 'Добавить вопрос',
			'add_new_item'  => 'Добавить новый вопрос',
			'edit'          => 'Редактировать',
			'edit_item'     => 'Редактировать вопрос',
			'new_item'      => 'Новый вопрос',
		),
		'description'         => '',
		'public'              => true,
		'publicly_queryable'  => true,
		'show_ui'             => true,
		'show_in_rest'        => false,
		'rest_base'           => '',
		'show_in_menu'        => true,
		'exclude_from_search' => false,
		'capability_type'     => 'post',
		'map_meta_cap'        => true,
		'hierarchical'        => false,
		'rewrite'             => array( 'slug'=>'faq/%faqcat%', 'with_front'=>false, 'pages'=>false, 'feeds'=>false, 'feed'=>false ),
		'has_archive'         => 'faq',
		'query_var'           => true,
		'supports'            => array( 'title', 'editor' ),
		'taxonomies'          => array( 'faqcat' ),
	) );

}

## Отфильтруем ЧПУ произвольного типа
// фильтр: apply_filters( 'post_type_link', $post_link, $post, $leavename, $sample );
add_filter('post_type_link', 'faq_permalink', 1, 2);
function faq_permalink( $permalink, $post ){
	// выходим если это не наш тип записи: без холдера %products%
	if( strpos($permalink, '%faqcat%') === false )
		return $permalink;

	// Получаем элементы таксы
	$terms = get_the_terms($post, 'faqcat');
	// если есть элемент заменим холдер
	if( ! is_wp_error($terms) && !empty($terms) && is_object($terms[0]) )
		$term_slug = array_pop($terms)->slug;
	// элемента нет, а должен быть...
	else
		$term_slug = 'no-faqcat';

	return str_replace('%faqcat%', $term_slug, $permalink );
}

Заметки

Плагин для реги типа записи

Есть удобный плагин, который позволяет регистрировать новые типы записей (постов) и новые таксономии: Custom Post Type UI

Переименование заголовков типа записи

Если тип записи уже зарегистрирован, но нам нужно назвать его как-то иначе, используйте следующий код.

Этот код показывает, как переименовать стандартный тип записи "Записи" в "Статьи":

## заменим слово «записи» на «статьи»
//$labels = apply_filters( "post_type_labels_{$post_type}", $labels );
add_filter('post_type_labels_post', 'rename_posts_labels');
function rename_posts_labels( $labels ){
	// заменять автоматически не пойдет например заменили: Запись = Статья, а в тесте получится так "Просмотреть статья"

	/* оригинал
		stdClass Object (
			'name'                  => 'Записи',
			'singular_name'         => 'Запись',
			'add_new'               => 'Добавить новую',
			'add_new_item'          => 'Добавить запись',
			'edit_item'             => 'Редактировать запись',
			'new_item'              => 'Новая запись',
			'view_item'             => 'Просмотреть запись',
			'search_items'          => 'Поиск записей',
			'not_found'             => 'Записей не найдено.',
			'not_found_in_trash'    => 'Записей в корзине не найдено.',
			'parent_item_colon'     => '',
			'all_items'             => 'Все записи',
			'archives'              => 'Архивы записей',
			'insert_into_item'      => 'Вставить в запись',
			'uploaded_to_this_item' => 'Загруженные для этой записи',
			'featured_image'        => 'Миниатюра записи',
			'set_featured_image'    => 'Задать миниатюру',
			'remove_featured_image' => 'Удалить миниатюру',
			'use_featured_image'    => 'Использовать как миниатюру',
			'filter_items_list'     => 'Фильтровать список записей',
			'items_list_navigation' => 'Навигация по списку записей',
			'items_list'            => 'Список записей',
			'menu_name'             => 'Записи',
			'name_admin_bar'        => 'Запись',
		)
	*/

	$new = array(
		'name'                  => 'Статьи',
		'singular_name'         => 'Статья',
		'add_new'               => 'Добавить статью',
		'add_new_item'          => 'Добавить статью',
		'edit_item'             => 'Редактировать статью',
		'new_item'              => 'Новая статья',
		'view_item'             => 'Просмотреть статью',
		'search_items'          => 'Поиск статей',
		'not_found'             => 'Статей не найдено.',
		'not_found_in_trash'    => 'Статей в корзине не найдено.',
		'parent_item_colon'     => '',
		'all_items'             => 'Все статьи',
		'archives'              => 'Архивы статей',
		'insert_into_item'      => 'Вставить в статью',
		'uploaded_to_this_item' => 'Загруженные для этой статьи',
		'featured_image'        => 'Миниатюра статьи',
		'filter_items_list'     => 'Фильтровать список статей',
		'items_list_navigation' => 'Навигация по списку статей',
		'items_list'            => 'Список статей',
		'menu_name'             => 'Статьи',
		'name_admin_bar'        => 'Статью', // пункте "добавить"
	);

	return (object) array_merge( (array) $labels, $new );
}

Подробнее читайте в вопросе.

Код register post type: wp-includes/post.php WP 4.8.2

<?php
function register_post_type( $post_type, $args = array() ) {
	global $wp_post_types;

	if ( ! is_array( $wp_post_types ) ) {
		$wp_post_types = array();
	}

	// Sanitize post type name
	$post_type = sanitize_key( $post_type );

	if ( empty( $post_type ) || strlen( $post_type ) > 20 ) {
		_doing_it_wrong( __FUNCTION__, __( 'Post type names must be between 1 and 20 characters in length.' ), '4.2.0' );
		return new WP_Error( 'post_type_length_invalid', __( 'Post type names must be between 1 and 20 characters in length.' ) );
	}

	$post_type_object = new WP_Post_Type( $post_type, $args );
	$post_type_object->add_supports();
	$post_type_object->add_rewrite_rules();
	$post_type_object->register_meta_boxes();

	$wp_post_types[ $post_type ] = $post_type_object;

	$post_type_object->add_hooks();
	$post_type_object->register_taxonomies();

	/**
	 * Fires after a post type is registered.
	 *
	 * @since 3.3.0
	 * @since 4.6.0 Converted the `$post_type` parameter to accept a WP_Post_Type object.
	 *
	 * @param string       $post_type        Post type.
	 * @param WP_Post_Type $post_type_object Arguments used to register the post type.
	 */
	do_action( 'registered_post_type', $post_type, $post_type_object );

	return $post_type_object;
}

Cвязанные функции

Из метки: Расширения движка addons

Еще из метки: post_type (произвольный тип записи)

Еще из раздела: Типы записей

register_post_type 108 комментариев
Полезные 9 Вопросы 6 Все
  • Denis cайт: denis-creative.com

    Kama, подскажите, пожалуйста, как правильно вывести архив для custom post types? Не просто вывод через query_post, а вывод архивов для Custom Taxonomy с пагинацией.
    Нигде в интернете не нашел полезной информации...

  • Денис cайт: www.dampi.ru

    С capabilities ничего не понял. Может мне не оно как бы надо, но задача передо мной стоит такая: кастомный тип записей, надо сделать так, что бы юзер мог просматривать, но не мог создавать и редактировать. Такое вообще возможно в рамках register_post_type?

    • Kama4489

      Там можно все настроить. Какой юзер, с какими правами? Если подписчик, то создавай тип записи как в примере (оставь параметры capability_type и capability по умолчанию) и все так и будет.

      • Денис cайт: www.dampi.ru

        Попробую описать задачу подробнее: есть два типа записей, назовем их "Заявки" и "Отчеты". Заявки все без исключения принадлежат админу и как бы желательно либо исключить вообще этот пункт из меню юзера, либо исключить возможность создания новых. Пока как-то так, сложно ставить задачу учитывая свои не совсем широкие познания вордпреса. Что скажешь?

        При всем при этот должен быть доступ к отчетам (создание и редактирование), но без возможности удаления, реально?

        P.S. Подписчик не видит если использовать пример, а участник уже имеет доступ к созданию новых записей

        • Kama4489

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

          Я так сразу могу ошибиться, но насколько помню тебе нужно указать capability_type=НОВЕО_ПРАВО и map_meta_cap=true. Больше не подскажу, читай разбирайся, если нет времени, пиши в личку, настрою за оплату, так время нет да и это делать надо, тестировать, многое можно просто не предусмотреть...

  • Дмитрий

    Добрый день!
    в примере "#2 Добавление элемента таксономии в ЧПУ" у меня
    /type/taxname/taxname/taxname/ - открывает как категорию и все ок
    /type/taxname/taxname/taxname/POSTNAME - 404 ошибка.

    Подскажите, пожалуйста, в чем может быть проблема?

  • Роман @

    Добрый день! Подскажите, пожалуйста!
    Есть обычные записи, которые выводятся не на главной, а на произвольной странице /articles
    Есть произвольный тип записей со слагом /doctors/, на которой находится архив врачей
    Так вот, при переходе к архиву /doctors/, ссылка /articles/ тоже становится активной. А при переходе к записи типа /doctors/*, активной остается только /articles/ (как родительская).
    Как «отделить» произвольный тип записей от основных записей, чтобы не было таких пересечений.

  • Павел @

    Как отключить на странице архива отображение миниатюр конкретной категории??
    В 'supports' => array() убрать thumbnail не помоагет

    Ответить4 месяца назад #
  • Андрей

    Сделал новый тип записей, создал рубрики, создаю пост, выбираю рубрику - все ок. Получаю url по типу site/custposttupe/namecat/namepost а вот если сменить рубрику, пост будет доступен как по ссылке site/custposttupe/namecat/namepost так и по новой ссылке site/custposttupe/namecat-2/namepost. Как бы это вылечить? Дубли не есть гуд. Спасибо.

    Ответить4 месяца назад #
    • Kama4489

      Так не должно быть, как минимум должен быть редирект автоматический. Но если его нет, то пропиши ручной...

      1
      Ответить4 месяца назад #
  • Алексей

    Скажите пожалуйста, хочу создать произвольный тип записи например slide с соответствующим меню в админке, чтобы можно было потом выводить все записи данного типа на произвольной странице, жду ответа спасибо))

    Ответить3 месяца назад #
  • Дмитрий @

    А как для примера #3 убрать из урла категорию? Но что бы корректно открывало как записи, так и категории.
    прим.
    /post_type/post_name/
    /post_type/tax__name/

    Спасибо за ответ.

    Ответить2 месяца назад #
    • Дмитрий @

      Получилось завести все с таким вот костылем в pre_get_posts

      if (!is_admin() && !$query->is_tax('имя моей таксономии') && $query->is_main_query() && !empty($query->query['имя моей таксономии'])) {
      	$query->query['name'] = $query->query['имя моей таксономии'];
      	$query->query['тип поста'] = $query->query['имя моей таксономии'];
      	$query->query_vars['name'] = $query->query['имя моей таксономии'];
      	$query->query_vars['тип поста'] = $query->query['имя моей таксономии'];
      	unset($query->query_vars['имя моей таксономии']);
      	$query->is_single = 1;
      	$query->is_archive = null;
        }

      Редиректы не ходят(особо и не нужно), но цель как таковая достигнута.
      pages и hierarchical при регистрации поста и таксономии включены, страницы корректно работают с дефолтным have_posts().
      /page/2.. тоже работает как для таксономии, так и на архивной странице.

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

      1
      Ответить2 месяца назад #
  • popay6 cайт: clubwp.ru

    Подскажите как в url сделать таксономию и на конце .html?

    Нашел такой код:

    function rewrite_rules($rules) {
    $new_rules = array();
    foreach (get_post_types() as $t)
    $new_rules[$t . '/(.+?)\.html$'] = 'index.php?post_type=' . $t . '&name=$matches[1]';
    return $new_rules + $rules;
    }
    add_action('rewrite_rules_array', 'rewrite_rules');
    
    function custom_post_permalink ($post_link) {
    global $post;
    if ( $post ) {
    $type = get_post_type($post->ID);
    $terms = get_object_term_cache( $post->ID, $taxonomy );
    return home_url() . '/' . $type . '/' . $post->post_name . '.html';
    }
    }
    add_filter('post_type_link', 'custom_post_permalink');

    Но как добавить туда таксономию не знаю. Подскажите как это сделать лучше?

    Ответить15 дней назад #

Здравствуйте, !

Ваш комментарий