Убираем лишний слаг в URL произвольного типа записей

Когда мы создаем новый тип записей, то при открытии страницы такой записи, Вордпресс добавляет в URL  название типа записи. Например, мы создали новый тип записей с названием orders:

Скопировано
register_post_type( 'orders', $args );
Показать код

Теперь, при открытии страницы этого типа записей, мы получим примерно такой URL:

 http://site.ru/orders/zakaz-1/ 

И мы хотим префикс orders убрать.

Сделать это можно, но надо иметь ввиду вот что. Когда мы уберем этот слаг, то может возникнуть ситуация, что если на сайте какая-то пользовательская запись и стандартная запись / страница Вордпресс имеют одно название, то они будут иметь одинаковый URL. Для ВП они станут неразличимы и при открытии такого URL он всегда будет открывать стандартную запись / страницу, а не пользовательскую запись.

Если это не смущает, то рассмотрим варианты как это можно сделать.

Внимание! После копирования любого куска кода отсюда в свой файл функций, не забываем обновить структуру постоянных ссылок.

С помощью кода

Если для нового типа записей не нужна архивная страница, то самым коротким вариантом будет такой.

Вариант 1

1) При создании нового типа записей добавляем в параметры функции register_post_type() такие строки:

Скопировано
'rewrite' => [
'slug' => '/',
'with_front' => false
],
Показать код

2) Пишем следующий код в файл функций:

Скопировано
add_filter( 'request', function( $request ) {
if( ! is_admin() ) {
$request['post_type'] = array( 'POST_TYPE', 'post', 'page' );
}
return $request;
});
Показать код

Вместо POST_TYPE надо вписать слаг создаваемого типа записей.

Вариант 2

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

Скопировано
add_action( 'init', function() {
	global $wp_rewrite;
	$wp_rewrite->add_rewrite_tag( '%orders%', '([^/]+)', 'orders=' );
	$wp_rewrite->add_permastruct( 'orders', '%orders%' );
});
add_filter( 'request',  function( $request ) {
	if( ! is_admin() ) {
		$request['post_type'] = array( 'orders', 'post', 'page' );
	}
	return $request;
});
Показать код

Здесь нужно везде слово orders (оно встречается тут 5 раз) заменить на слаг нужного типа записей.

Вариант 3

Этот код, в отличие от первых двух, оставляет рабочей архивную страницу произвольного типа записей. Но у него есть другое условие - в настройках постоянных ссылок должен быть выбран пункт "Название записи".

Скопировано
add_filter( 'post_type_link', function( $post_link, $post, $leavename ) {
	if( $post->post_type != 'orders' || $post->post_status != 'publish' ) return $post_link;
	return str_replace( '/' . $post->post_type . '/', '/', $post_link );
}, 10, 3 );
add_action( 'pre_get_posts', function( $query ) {
	if( ! $query->is_main_query() ) return;
	if( count( $query->query ) != 2 || ! isset( $query->query['page'] ) ) return;
	if( ! empty( $query->query['name'] ) ) {
		$query->set( 'post_type', array( 'orders', 'post', 'page' ) );
	}
});
Показать код

Здесь так же нужно везде слово orders заменить на слаг нужного типа записей.

С помощью плагинов

Remove CPT base

Наверно лучший плагин для этой цели. Минимум только необходимых настроек. Архивная страница нового типа записей продолжает работать корректно. Все работает так же и если в настройках постоянных ссылок выбран вариант отличный от "Название записи".