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

12

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

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

Какой лучший подход для этого? ура

Fran
источник

Ответы:

15

Вам нужно сделать три важные вещи:

  1. Создайте пользовательское правило перезаписи, чтобы превратить части URI в значения, передаваемые index.php.
  2. Добавьте myrouteи myargumentв белый список переменных запроса WordPress, чтобы WordPress не просто игнорировал их, когда они появляются в строке запроса.
  3. Сбросьте правила перезаписи.

Во-первых, я собираюсь порекомендовать вам вместо http://www.example.org/myroute/myargumentкакого-то специального префикса или суффикса указать, когда URI следует рассматривать как один из этих специальных «маршрутов». Ради этого примера я выбрал префикс api, чтобы он был 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' );

// flush_rules() if our rules are not yet included
function my_flush_rules() {
    $rules = get_option( 'rewrite_rules' );

    if ( ! isset( $rules['api/(.*?)/(.+?)'] ) ) {
        global $wp_rewrite;
        $wp_rewrite->flush_rules();
    }
}

// Adding a new rule
function my_insert_rewrite_rules( $rules ) {
    $newrules = array();
    $newrules['api/(.*?)/(.+?)'] = 'index.php?myroute=$matches[1]&myargument=$matches[2]';
    return $newrules + $rules;
}

// Adding the id var so that WP recognizes it
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это не таксономия, термин или родительская страница?

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

eddiemoya
источник
1
Полезное примечание: правила определены в my_insert_rewrite_rulesследующем порядке! Сначала начните с самого длинного правила, затем перейдите к самому простому, иначе / api / myroute переопределит / api / myroute / myargument.
EMC
1
@npc Это важный момент, о котором следует помнить при создании пользовательских правил перезаписи, они также могут столкнуться с этим. В приведенном выше примере это не проблема, потому что / api / myroute просто не будет правильным путем.
eddiemoya
Как кто-то может загрузить пользовательский шаблон из своего каталога плагинов при запросе страницы example.org/api/myroute/myargument ?
Мэтт Киз
1
Вот актуальное и полное решение WordPress
Имран Захур
6

Чтобы немного рассказать о том, что eddiemoya сделал выше:

Как и оригинальный постер этого вопроса, я хотел создать пользовательскую перезапись, а также предоставить собственный шаблон для этой страницы перезаписи. Код от 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 )
    {
        //try and get the query var we registered in our query_vars() function
        $account_page = get_query_var( 'account_page' );

        //if the query var has data, we must be on the right page, load our custom template
        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' ) );

// One time activation functions
register_activation_hook( PATH_TO_PLUGIN_FILE, array( new Your_Class, 'flush_rules' ) );
Мэтт Кис
источник
1
Вы также можете просто использовать add_rewrite_endpoint, который сгенерирует правило для вас и добавит запрос var за один раз. также, если вы добавляете свои собственные правила перезаписи, я предлагаю add_rewrite_ruleфункцию вместо фильтрации rewrite_rules_array.
Майло
Благодаря Майло, я обновил код, чтобы использовать add_rewrite_rule вместо фильтрации массива перезаписи. Я посмотрел на add_rewrite_endpoint, но думаю, что add_rewrite_tag может лучше подойти для моих нужд. Кажется, что add_rewrite_endpoint в основном полезен, если вы хотите добавить дополнительный аргумент в существующие перезаписи WP. Поправь меня, если я здесь не прав.
Мэтт Киз
1
Мне нравится объектно-ориентированный подход. Слишком много разработчиков WP все еще не знают, как использовать ООП. Спасибо за попытку восстановить мою веру в разработчиков PHP. ;)
Арвид