Использование register_post_type() для модификации существующего типа записей
Существует множество ситуаций, когда тема или плагин регистрирует тип записи, и вам нужно его изменить. Конечно, есть функции add_post_type_support()
и remove_post_type_support()
, но они не дают доступа ко всему списку аргументов, которые принимает register_post_type()
. В частности, может потребоваться отключить архив типа записей, скрыть интерфейс администратора, скрыть из поиска и т.д., оставив при этом остальные настройки типа записей без изменений.
Страница Codex для register_post_type()
дразнит нас следующим:
Описание
Создать или изменить тип записи.
Но когда я пытался сделать это раньше, казалось, что это не работает. Действительно ли эта функция предназначена для модификации типов записей, и если да, то можно ли просто переопределить несколько аргументов, оставив остальные без изменений?
Учитывая, что даже не существует функции deregister_post_type()
, я не понимаю, как это можно сделать.

После некоторых исследований я обнаружил, что ни один из этих ответов не актуален.
Начиная с 8 декабря 2015 года WordPress включает новый фильтр register_post_type_args
, который позволяет вам изменять аргументы зарегистрированного типа записи.
function wp1482371_custom_post_type_args( $args, $post_type ) {
if ( $post_type == "animal-species" ) {
$args['rewrite'] = array(
'slug' => 'animal' // ЧПУ для типа записи "animal-species"
);
}
return $args;
}
add_filter( 'register_post_type_args', 'wp1482371_custom_post_type_args', 20, 2 );

Что делать, если нужно обновить его после регистрации во время выполнения? Например: после init

@LucasBustamante Это не имеет значения. Просто вызовите строку 'add_filter' в вашем плагине/теме, а не в экшене. Фильтр будет вызываться при каждой функции register_post_type
. Единственный сценарий, когда мой код не сработает - это если тип записи регистрируется некорректно. Все типы записей должны регистрироваться во время хука init. Из кодекса: "register_post_type не будет работать, если вызван до 'init', и аспекты вновь созданного или изменённого типа записи будут работать некорректно, если вызваны позже." Если вам всё ещё нужна помощь, предлагаю опубликовать больше деталей в новом вопросе.

то есть этот код изменит 'slug-of-post', как в 'sitename/projects/slug-of-post'??

@Krys Не совсем понимаю вопрос, но для ясности: Если у вас есть "example.org/animal-species/slug-of-post", этот код позволяет изменить "animal-species" на просто "animal", так что URL станет "example.org/animal/slug-of-post", а архивная страница, если включена, будет "example.org/animal/". Без необходимости изменять название типа записи.

Эта функция действительно предназначена для изменения типов записей?
Да.
И если да, можно ли просто переопределить несколько аргументов, оставив остальные без изменений?
Нет. Если вы хотите изменить аргументы типа записи, вам нужно использовать get_post_type_object
для получения объекта типа записи, изменить нужные вам параметры в нем, а затем повторно зарегистрировать его, используя ваш измененный тип в качестве нового параметра $args.

Будет ли правильным делать два последовательных вызова с измененными аргументами для одной и той же функции register_post_type
? Я предполагаю, что да, исходя из вашего "Да.", и это не вызывает ошибок, а дает желаемый эффект. Реальный случай - это второй вариант, который я привожу в этом ответе: http://wordpress.stackexchange.com/a/74331/12615

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

Вот пример использования фильтра 'registered_post_type'
для изменения типа записи в другом плагине.
Плагин, который я использовал, не включал menu_icon в своём определении, поэтому я решил добавить свою иконку.
<?php
/**
* Добавляем иконку меню для пользовательского типа записи WP-VeriteCo Timeline
*
* Плагин таймлайна не имеет иконки меню, поэтому мы подключаемся к 'registered_post_type'
* и добавляем свою.
*
* @param string $post_type название типа записи
* @param object $args аргументы типа записи
*/
function wpse_65075_modify_timeline_menu_icon( $post_type, $args ) {
// Убедимся, что редактируем только нужный тип записи
if ( 'timeline' != $post_type )
return;
// Устанавливаем иконку меню
$args->menu_icon = get_stylesheet_directory_uri() . '/img/admin/menu-timeline.png';
// Модифицируем объект типа записи
global $wp_post_types;
$wp_post_types[$post_type] = $args;
}
add_action( 'registered_post_type', 'wpse_65075_modify_timeline_menu_icon', 10, 2 );

Подключитесь к хуку 'registered_post_type'
после того, как другой код зарегистрирует его. Этот хук вызывается в конце функции register_post_type()
. Вы получаете два аргумента: $post_type
и $args
.
Теперь вы можете изменить любые параметры для этого типа записи. Проверьте $GLOBALS['wp_post_types']
для просмотра доступных опций.

Спасибо, что направили меня к этому хуку. Это отвечает на (более важный) вопрос о том, как изменить тип записи, но что насчёт описания register_post_type()
, где упоминается "модификация"? Это просто ошибка? Мне стоит оседлать своего интернет-коня и немедленно изгнать это из Кодекса?

Я столкнулся с такой же проблемой в плагине The Events Calendar.
Я добавил следующий код в function.php, чтобы изменить тип записи tribe_organizer:
function tribe_modify_organizer() {
//Новые аргументы
$tribe_organizer_args = get_post_type_object('tribe_organizer'); // получаем тип записи для изменения
$tribe_organizer_args-> taxonomies = array('post_tag' , 'tribe_events_cat'); // добавляем поддержку таксономий
$tribe_organizer_args-> exclude_from_search = false; // показывать в результатах поиска
//перерегистрируем тот же тип записи с новыми аргументами
register_post_type( 'tribe_organizer', $tribe_organizer_args );
}
add_action( 'init', 'tribe_modify_organizer', 100 );

Не знаю, насколько это коряво, но вы можете изменять глобальный плейсхолдер GLOBAL
"на лету", когда вам нужно манипулировать одним аргументом. Вот как мы используем непубличный тип записи contents
, чтобы он был доступен в админ-меню. Мы добавляем хуки непосредственно перед и после отрисовки меню:
function entex_theme_make_contents_public(){
$GLOBALS['wp_post_types']['contents']->public = true;
}
add_action('admin_menu', 'entex_theme_make_contents_public', 10);
function entex_theme_make_contents_private_again(){
$GLOBALS['wp_post_types']['contents']->public = '';
}
add_action('admin_menu', 'entex_theme_make_contents_private_again', 12);
В нашем случае мы хотим, чтобы плагин Admin Menu Post List принимал наш тип записи, так как он вызывает return get_post_types(array('public' => true));
внутри своего хука с приоритетом 11...
Разработчики - пожалуйста, оставьте комментарий, если это может вызвать какие-либо проблемы.
