Пользовательский маршрут плагина в WordPress
Итак, мой вопрос довольно прост. Мне нужно реализовать некоторые пользовательские правила маршрутизации для моего плагина. Эти маршруты должны принимать только один аргумент (ничего сложного) и выглядеть так: http://www.example.org/myroute/myargument
В идеале, это должно вызывать пользовательский класс и отображать пользовательский шаблон (который мог бы напрямую обращаться к классу).
Какой подход будет лучшим? Спасибо
Вам необходимо выполнить три важных действия:
- Создать пользовательское правило перезаписи (rewrite rule), чтобы преобразовать части URI в значения, передаваемые в
index.php
. - Добавить
myroute
иmyargument
в белый список переменных запроса WordPress, чтобы WordPress не игнорировал их при появлении в строке запроса. - Сбросить правила перезаписи (flush rewrite rules).
Во-первых, я рекомендую вместо http://www.example.org/myroute/myargument
использовать какой-нибудь специальный префикс или суффикс, чтобы обозначить, когда URI должен считаться одним из этих специальных «маршрутов». Для примера я выбрал префикс api
, так что URI будет выглядеть как http://www.example.org/api/myroute/myargument
. Я выбрал api
, потому что когда я делал что-то RESTful, похожее на то, над чем вы работаете, это было для API.
Код
add_filter( 'rewrite_rules_array', 'my_insert_rewrite_rules' );
add_filter( 'query_vars', 'my_insert_query_vars' );
add_action( 'wp_loaded', 'my_flush_rules' );
// Сброс правил, если наши правила еще не включены
function my_flush_rules() {
$rules = get_option( 'rewrite_rules' );
if ( ! isset( $rules['api/(.*?)/(.+?)'] ) ) {
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
}
// Добавление нового правила
function my_insert_rewrite_rules( $rules ) {
$newrules = array();
$newrules['api/(.*?)/(.+?)'] = 'index.php?myroute=$matches[1]&myargument=$matches[2]';
return $newrules + $rules;
}
// Добавление переменных, чтобы WordPress их распознавал
function my_insert_query_vars( $vars ) {
array_push( $vars, 'myroute', 'myargument' );
return $vars;
}
Краткое объяснение
Все довольно просто. Регулярное выражение добавляется в список всех правил перезаписи WordPress, и ваш пользовательский шаблон оказывается в начале списка. Когда шаблон совпадает, WordPress прекращает поиск по списку правил перезаписи и использует захваченные значения регулярного выражения вместо ссылок ($matches[1]
и $matches[2]
) в строке запроса, передаваемой в index.php
.
Добавление переменных запроса myroute
и myargument
в белый список заставляет WordPress обращать на них внимание, а не игнорировать их.
Альтернативный способ «пространства имен» для вашего пользовательского маршрута
Если вы хотите избежать использования /api/
в качестве префикса, вы можете использовать переменную/поле строки запроса. Для этого нужно изменить регулярное выражение на что-то вроде (.*?)/(.+?)\\?api=1
и добавить api
как дополнительный параметр в вызов array_push()
в функции my_insert_query_vars()
.
Это изменит пользовательский маршрут так, что он будет срабатывать каждый раз, когда api=1
является первым элементом строки запроса, например, для http://example.com/anytext/anytext?api=1
.
Игнорируйте использование термина «пространство имен» — он использован для краткости.
Если вы не «пространственно именуете» маршрут с помощью префикса или суффикса, у вас возникнут конфликты шаблонов URI. Это потому, что WordPress не сможет отличить ваш пользовательский шаблон от шаблона, предназначенного для записи или страницы. Как WordPress узнает, что myroute
— это не таксономия, термин или родительская страница?
Надеюсь, это поможет.

Полезное замечание: правила, определенные в my_insert_rewrite_rules
, следуют порядку определения! Начинайте с самого длинного правила, затем переходите к более простым, иначе /api/myroute переопределит /api/myroute/myargument.

@npc Это важный момент, о котором нужно помнить при создании пользовательских правил перезаписи - они могут конфликтовать таким образом. В приведенном выше примере это не проблема, потому что /api/myroute просто не будет допустимым путем.

Как можно загрузить пользовательский шаблон из директории плагина при запросе страницы http://www.example.org/api/myroute/myargument?

Вот актуальное и полное решение от WordPress: https://codex.wordpress.org/Rewrite_API/add_rewrite_rule

Чтобы немного расширить то, что сделал eddiemoya выше:
Как и оригинальный автор этого вопроса, я хотел создать собственные правила перезаписи URL, а также использовать пользовательский шаблон для этой страницы. Код от edditmoya направил меня в правильном направлении, и я добавил дополнительную функцию для загрузки моего пользовательского шаблона при обращении к странице.
Пользовательский шаблон может располагаться где угодно, в моем случае он хранится в директории плагина.
Также я хотел проверять необходимость сброса правил перезаписи только при активации плагина, поэтому поместил это в register_activation_hook.
Ниже приведен полный пример того, что я сделал:
ОБНОВЛЕНО упрощено на основе совета от milo
class Your_Class
{
public function init()
{
add_filter( 'template_include', array( $this, 'include_template' ) );
add_filter( 'init', array( $this, 'rewrite_rules' ) );
}
public function include_template( $template )
{
// пытаемся получить переменную запроса, которую мы зарегистрировали в функции query_vars()
$account_page = get_query_var( 'account_page' );
// если переменная запроса содержит данные, значит мы на нужной странице, загружаем наш пользовательский шаблон
if ( $account_page ) {
return PATH_TO_PLUGIN_TEMPLATES_DIR . 'register.php';
}
return $template;
}
public function flush_rules()
{
$this->rewrite_rules();
flush_rewrite_rules();
}
public function rewrite_rules()
{
add_rewrite_rule( 'account/(.+?)/?$', 'index.php?account_page=$matches[1]', 'top');
add_rewrite_tag( '%account_page%', '([^&]+)' );
}
}
add_action( 'plugins_loaded', array( new Your_Class, 'init' ) );
// Функции однократного выполнения при активации
register_activation_hook( PATH_TO_PLUGIN_FILE, array( new Your_Class, 'flush_rules' ) );

вы также можете просто использовать add_rewrite_endpoint
, который автоматически создаст правило для вас и добавит query var за один шаг. также, если вы добавляете свои собственные правила перезаписи, я рекомендую функцию add_rewrite_rule
вместо фильтрации rewrite_rules_array
.

Спасибо, Мило, я обновил код, чтобы использовать add_rewrite_rule вместо фильтрации массива rewrite. Я посмотрел на add_rewrite_endpoint, но думаю, что add_rewrite_tag может лучше подойти для моих нужд. Похоже, что add_rewrite_endpoint в основном полезен, если вы хотите добавить дополнительный аргумент к существующим WP rewrite. Поправьте меня, если я ошибаюсь.
