Пользовательский маршрут плагина в WordPress

10 июл. 2012 г., 22:14:25
Просмотры: 23K
Голосов: 16

Итак, мой вопрос довольно прост. Мне нужно реализовать некоторые пользовательские правила маршрутизации для моего плагина. Эти маршруты должны принимать только один аргумент (ничего сложного) и выглядеть так: http://www.example.org/myroute/myargument

В идеале, это должно вызывать пользовательский класс и отображать пользовательский шаблон (который мог бы напрямую обращаться к классу).

Какой подход будет лучшим? Спасибо

0
Все ответы на вопрос 2
4
16

Вам необходимо выполнить три важных действия:

  1. Создать пользовательское правило перезаписи (rewrite rule), чтобы преобразовать части URI в значения, передаваемые в index.php.
  2. Добавить myroute и myargument в белый список переменных запроса WordPress, чтобы WordPress не игнорировал их при появлении в строке запроса.
  3. Сбросить правила перезаписи (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 — это не таксономия, термин или родительская страница?

Надеюсь, это поможет.

11 июл. 2012 г. 03:28:19
Комментарии

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

emc emc
25 февр. 2014 г. 19:42:52

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

eddiemoya eddiemoya
3 мар. 2014 г. 21:37:13

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

Matt Keys Matt Keys
21 сент. 2014 г. 13:36:17

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

Imran Zahoor Imran Zahoor
12 сент. 2015 г. 23:15:56
3

Чтобы немного расширить то, что сделал 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' ) );
24 сент. 2014 г. 02:14:05
Комментарии

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

Milo Milo
24 сент. 2014 г. 02:31:05

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

Matt Keys Matt Keys
24 сент. 2014 г. 03:03:30

Мне нравится объектно-ориентированный подход. Слишком много WP-разработчиков до сих пор не умеют использовать ООП. Спасибо, что пытаетесь восстановить мою веру в PHP-разработчиков. ;)

Arvid Arvid
19 февр. 2018 г. 19:36:36