Пользовательские конечные точки (endpoints) для постоянных ссылок произвольного типа записей
У меня есть произвольный тип записей "destinations", и я установил маску EP для этого типа записей на EP_PERMALINK по умолчанию. Я добавил несколько конечных точек следующим образом:
add_filter( 'query_vars', 'add_query_vars');
function add_query_vars($vars){
$vars[] = "tours"; // Добавляем переменную tours
$vars[] = "activities"; // Добавляем переменную activities
return $vars;
}
add_action('init', 'add_endpoints');
function add_endpoints(){
global $wp_rewrite;
// Регистрируем конечные точки
add_rewrite_endpoint('tours', EP_PERMALINK);
add_rewrite_endpoint('activities', EP_PERMALINK);
// Сбрасываем правила перезаписи
$wp_rewrite->flush_rules();
}
Когда я тестирую это на обычной записи, происходит перенаправление на нужный мне шаблон (у меня есть обработчик перенаправления шаблонов для хука single template):
Например: somesite.com/test-category/test/activities/
Но для произвольного типа записей (который является иерархическим) конечная точка просто удаляется из URL, и остается шаблон single-destination.php
Например: somesite.com/destination/south-africa/kruger-national-park/activities/
превращается в
somesite.com/destination/south-africa/kruger-national-park/
Любая помощь или подсказка будет очень ценной. Я мучаюсь с этим уже несколько часов безрезультатно :(
Спасибо

Несколько моментов. Во-первых, названия ваших функций должны иметь уникальный префикс. WordPress — это большая экосистема, и кто-то уже наверняка использовал все общие названия функций, которые вы можете придумать.
Во-вторых, add_rewrite_endpoint
автоматически добавляет переменные запроса, поэтому вам не нужно это:
add_filter( 'query_vars', 'add_query_vars');
function add_query_vars($vars){
$vars[] = "tours";
$vars[] = "activities";
return $vars;
}
Сброс правил перезаписи при каждой загрузке — плохая идея. Это нужно делать только один раз после добавления новых правил, например, при активации плагина. Поэтому вашу функцию add_endpoints
можно сократить до такого вида (с более подходящим названием, как упоминалось выше):
<?php
add_action('init', 'wpse42279_add_endpoints');
function wpse42279_add_endpoints()
{
add_rewrite_endpoint('tours', EP_PERMALINK);
add_rewrite_endpoint('activities', EP_PERMALINK);
}
Это будет работать для записей. Если вам нужно, чтобы это работало для страниц или других иерархических типов записей, используйте маску конечной точки EP_PAGES
.
<?php
add_action('init', 'wpse42279_add_endpoints');
function wpse42279_add_endpoints()
{
add_rewrite_endpoint('tours', EP_PAGES);
add_rewrite_endpoint('activities', EP_PAGES);
}
Но даже так это не будет работать так, как вы ожидаете. Конечные точки устанавливают переменную запроса равной тому, что идет после них. Например, если ваш URL выглядит так:
yoursite.com/some-country/some-city/activities/asdf
то переменная запроса activities будет равна "asdf". Если после activities
ничего нет, переменная запроса будет пустой (но установленной), поэтому она всегда будет оцениваться как false при попытке её перехватить:
<?php
add_action( 'template_redirect', 'wpse42279_catch_vars' );
function wpse42279_catch_vars()
{
if( get_query_var( 'tours' ) )
{
// выполняем действия!
exit();
}
}
Это можно обойти, фильтруя request
и изменяя значение переменных tours и activities на true, если они установлены.
<?php
add_filter( 'request', 'wpse42279_filter_request' );
function wpse42279_filter_request( $vars )
{
if( isset( $vars['tours'] ) ) $vars['tours'] = true;
if( isset( $vars['activities'] ) ) $vars['activities'] = true;
return $vars;
}
Рекомендую ознакомиться с руководством по Rewrite API, которое я написал. Однако, основные моменты, касающиеся вашего вопроса, изложены выше.

Спасибо за потрясающий ответ! Я внес изменения согласно вашему посту и руководству. Но, похоже, WordPress перенаправляет/удаляет конечную точку и любые переменные после нее при загрузке URL. Не уверен, это каноническое перенаправление или что-то еще. Но он удаляет только зарегистрированные конечные точки. Если я добавлю что-то случайное в конец URL, то получу 404. Но "tours" или "activities" удаляются или перенаправляют на URL отдельного направления. :(

Кажется, я нашел проблему. Она связана с настройками постоянных ссылок. У меня было пользовательское значение - /%category%/%postname%/. Но если я установлю просто /%postname%/, то все работает, пока не понимаю почему, но разберусь. Спасибо \0/

Попробуй вернуть обратно /%category%/%postname%/ - теперь это может снова заработать. Подозреваю, что причина, по которой WP удалял ваши данные, заключалась в необходимости сбросить правила перезаписи. (Возможно.)

У меня тоже были пользовательские настройки постоянных ссылок. Я просто зашел в Настройки постоянных ссылок и нажал Сохранить изменения, ничего не меняя, после этого конечная точка заработала.
