Переопределение/Изменение ЧПУ (slug) Пользовательского Типа Записи Плагина
Возможно ли переопределить/изменить ЧПУ (slug) существующего пользовательского типа записи плагина (без прямого редактирования плагина)?
То есть, если Плагин X создает пользовательский тип записи с ЧПУ /uncookedtoast/, возможно ли добавить фильтр в functions.php (или что-то подобное), чтобы изменить ЧПУ на /bread/?

Да, это возможно, но если плагин создает пользовательский тип записи с использованием параметра rewrite => array('slug' => 'post_type')
, то маловероятно, что вы сможете заменить слаг.
При создании пользовательских типов записей правила перезаписи URL сохраняются в базе данных. В зависимости от действия, которое инициирует создание типа записи (например, действие init), WordPress сбросит правила перезаписи и восстановит слаги пользовательских типов записей, независимо от внесенных изменений.
Тем не менее, вы можете задать собственные слаги для пользовательских типов записей. В следующем примере предполагается, что у вас есть пользовательский тип записи movies
, и вы пытаетесь изменить слаг /movies/
на /films/
.
Для полноты картины, вот базовая функция для определения пользовательского типа записи movies
. Плагин, на который вы ссылаетесь, должен делать что-то подобное:
function movies_register_post_type() {
register_post_type(
'movies',
array(
'labels' => array(
'name' => __('Фильмы'),
'singular_name' => __('Фильм')
),
'public' => true,
'has_archive' => true,
'rewrite' => array(
'slug' => 'movies'
)
)
);
} // end example_register_post_type
add_action('init', 'movies_register_post_type');
Вы можете изменить таблицу опций, добавив собственные правила на основе существующего типа записи.
Вкратце, мы сделаем следующее:
- Возьмем существующие правила и создадим новые с собственными слагами
- Присвоим новому правилу более высокий приоритет, чем слагу пользовательского типа записи
Вот как это можно реализовать:
function add_custom_rewrite_rule() {
// Сначала попытаемся загрузить правила перезаписи на случай,
// если используется структура постоянных ссылок по умолчанию.
if( ($current_rules = get_option('rewrite_rules')) ) {
// Затем пройдемся по каждому пользовательскому правилу, добавляя новое правило,
// которое заменяет 'movies' на 'films' с более высоким приоритетом,
// чем у существующего правила.
foreach($current_rules as $key => $val) {
if(strpos($key, 'movies') !== false) {
add_rewrite_rule(str_ireplace('movies', 'films', $key), $val, 'top');
} // end if
} // end foreach
} // end if/else
// ...и сбрасываем правила
flush_rewrite_rules();
} // end add_custom_rewrite_rule
add_action('init', 'add_custom_rewrite_rule');
Теперь у вас будет два способа доступа к фильмам:
/movies/Назад-в-будущее
/films/Назад-в-будущее
Обратите внимание, что я не рекомендую подключать функцию add_custom_rewrite_rule
к действию init
, так как оно срабатывает слишком часто. Это лишь пример. Лучше использовать активацию темы, активацию плагина, действие save_post и т.д. В зависимости от задачи, функцию может потребоваться вызвать один раз или несколько.
На этом этапе вы можете обновить постоянные ссылки для пользовательского типа записи, чтобы использовать слаг /movies/
. Например, если перейти по адресу /films/
, вы увидите список всех фильмов, но при наведении на заголовок станет видно, что по-прежнему используется слаг /movies/
.
Для дальнейшей доработки можно реализовать 301 редирект, чтобы все ссылки на /movies/
перенаправлялись на соответствующие /films/
, но это зависит от ваших целей.

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

В зависимости от вашей темы, это можно сделать на уровне шаблона. Когда вы видите вызов 'the_title()', вы можете заменить его на $title = get_the_title(), а затем заменить '/movies/' в $title на '/films/'.

Что делать, если новый ярлык (slug) должен динамически создаваться из мета-значения текущей записи? Мне нужно использовать $post
в функции add_custom_rewrite_rule()
, но в админке WordPress выдается ошибка 'Trying to get property of non-object'. Как правильно получить доступ к $post, чтобы получить мета-значение?

Этот код отлично сработал для моей дочерней темы. Нужно было изменить слаг "program" на "place".
/*
ИЗМЕНЕНИЕ СЛАГОВ ПРОИЗВОЛЬНЫХ ТИПОВ ЗАПИСЕЙ
*/
function change_post_types_slug( $args, $post_type ) {
/*слаг типа записи item*/
if ( 'program' === $post_type ) {
$args['rewrite']['slug'] = 'place';
}
return $args;
}
add_filter( 'register_post_type_args', 'change_post_types_slug', 10, 2 );
/*
ИЗМЕНЕНИЕ СЛАГОВ ТАКСОНОМИЙ, слаги используются для архивных страниц
*/
function change_taxonomies_slug( $args, $taxonomy ) {
/*категория item*/
if ( 'program-category' === $taxonomy ) {
$args['rewrite']['slug'] = 'locations';
}
return $args;
}
add_filter( 'register_taxonomy_args', 'change_taxonomies_slug', 10, 2 );

Работает идеально, я также использовал это для тегов, добавив соответствующее правило. Необходимо обновить постоянные ссылки, выполнив сохранение на странице настроек > постоянные ссылки. Спасибо!

Отлично работает для изменения других аргументов. Мне нужно было установить $args['has_archive'] = false
, и это сработало.

В моем случае был плагин (необходимый для работы темы), который регистрировал произвольный тип записи, и я хотел изменить некоторые его параметры, в том числе ярлык (slug).
Что я сделал — перерегистрировал (своего рода перезапись функции регистрации плагина) произвольный тип записи, добавив следующий код в файл functions.php
дочерней темы:
function my-theme-name_post_type_my-custom-post-type-name()
{
$labels = array(
...
);
$args = array(
...
'rewrite' => array(
'slug' => __('the-slug-of-your-choise', 'the-textdomain-of-your-choise-for-translation-if-needed'),
),
);
register_post_type('the-custom-post-type-name-registered-by-the-plugin', $args);
}
add_action('init', 'my-theme-name_post_type_my-custom-post-type-name');
Как видите, вы можете изменить ярлык (slug), просто добавив следующее в массив $args
:
'rewrite' => array(
'slug' => __('the-slug-of-your-choise', 'the-textdomain-of-your-choise-for-translation-if-needed'),
)
Подробнее об этом можно узнать здесь: https://developer.wordpress.org/reference/functions/register_post_type/
ОЧЕНЬ ВАЖНО
Не забудьте обновить постоянные ссылки, чтобы изменения вступили в силу и вы могли получить доступ к соответствующим записям. Перейдите в настройки постоянных ссылок и просто нажмите "Сохранить". После этого все должно заработать!

function change_portfolio_slug() {
$args = get_post_type_object( 'portfolio' );
if ( ! empty( $args ) ) {
$args->rewrite['slug'] = 'project';
register_post_type( 'portfolio', $args );
}
}
add_action( 'init', 'change_portfolio_slug', 20 );
В моём случае плагин объявляет пользовательский тип записи "portfolio" с параметром 'rewrite' => array( 'slug' => 'portfolio')
, используя хук для действия 'init': add_action( 'init', 'some_plugin_custom_posts_init' );
.
Приведённый выше фрагмент кода, размещённый в файле functions.php темы, определяет новую функцию change_portfolio_slug()
, которая изменяет параметр rewrite для типа записи portfolio, меняя его ярлык (slug) на "project". Затем мы используем функцию register_post_type()
для регистрации типа записи с изменёнными параметрами.
Функция add_action()
подключает функцию change_portfolio_slug()
к действию init, чтобы она выполнялась при инициализации WordPress.
В последней строке фрагмента add_action( 'init', 'change_portfolio_slug', 10 );
число 10
обозначает приоритет хука. Если вам нужно изменить приоритет, вы можете заменить 10
на другое число. В моём случае рабочим приоритетом оказалось 20
.
Обратите внимание, что после внесения этих изменений вам может потребоваться обновить постоянные ссылки, чтобы новая структура URL применилась корректно. Это можно сделать в разделе Настройки → Постоянные ссылки в админ-панели WordPress, нажав кнопку "Сохранить изменения".
