Wordpress中的自定义插件路由


12

好吧,我的问题很简单。我需要为插件实现一些自定义路由规则。这些路由只需要一个参数(所以没有什么复杂的),看起来像是:http : //www.example.org/myroute/myargument

理想情况下,这将调用一个自定义类,并显示一个自定义模板(可以直接访问该类)。

最好的方法是什么?干杯

Answers:


15

您需要做三件事:

  1. 创建一个自定义重写规则,以将URI的一部分转换成传递给的值index.php
  2. 在WordPress的查询变量白名单中添加myroutemyargument,以便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;
}

快速分解

一切都非常简单。regex模式已添加到WordPress中所有重写规则的列表中,而您的自定义模式位于列表的顶部。匹配模式后,WordPress将停止浏览重写规则列表,并使用正则表达式的捕获值代替传递给的查询字符串中的引用($matches[1]$matches[2]index.php

添加查询变量myroutemyargument白名单只是让WordPress注意而不是丢弃它们。

“命名”自定义路线的另一种方法

如果要避免/api/用作前缀,则可以改用查询字符串变量/字段。为此,您需要将正则表达式更改为(.*?)/(.+?)\\?api=1,然后将其api作为附加参数添加到中进行的array_push()调用中my_insert_query_vars()

这将更改自定义路由,以使其api=1在查询字符串的第一个元素(无论何时触发)时触发http://example.com/anytext/anytext?api=1

忽略术语“命名空间”的使用-只是为了简洁起见。

如果您不使用前缀或后缀来命名空间,那么您将遇到冲突的URI模式。这是因为WordPress无法将您的自定义模式与打算用作帖子或页面的自定义模式区分开。WordPress如何知道这myroute不是分类法,术语或父页面?

希望这可以帮助。


1
方便注意:按照定义my_insert_rewrite_rules顺序定义的规则!首先从最长的规则开始,然后逐步简化,否则/ api / myroute将覆盖/ api / myroute / myargument。
emc

1
@npc这是创建自定义重写规则时要注意的重要一点,它们也可能以这种方式冲突。但是在上面的示例中,这不是问题,因为/ api / myroute根本不是有效路径。
eddiemoya 2014年

每当请求example.org/api/myroute/myargument页面时,有人如何从其插件目录中加载自定义模板?
Matt Keys 2014年

1
这是wordpress的实际且完整的解决方案:codex.wordpress.org/Rewrite_API/add_rewrite_rule
Imran Zahoor

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功能,而不要使用filter rewrite_rules_array
米洛(Milo)2014年

感谢Milo,我更新了代码以使用add_rewrite_rule而不是过滤重写数组。我查看了add_rewrite_endpoint,但我认为add_rewrite_tag可能更适合我的需求。如果要向现有的WP重写添加额外的参数,似乎add_rewrite_endpoint最有用。如果我在这里错了,请纠正我。
Matt Keys

1
我喜欢面向对象的方法。太多的WP开发人员仍然不知道如何使用OOP。感谢您尝试恢复对PHP开发人员的信念。;)
Arvid
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.