好吧,我的问题很简单。我需要为插件实现一些自定义路由规则。这些路由只需要一个参数(所以没有什么复杂的),看起来像是:http : //www.example.org/myroute/myargument
理想情况下,这将调用一个自定义类,并显示一个自定义模板(可以直接访问该类)。
最好的方法是什么?干杯
好吧,我的问题很简单。我需要为插件实现一些自定义路由规则。这些路由只需要一个参数(所以没有什么复杂的),看起来像是:http : //www.example.org/myroute/myargument
理想情况下,这将调用一个自定义类,并显示一个自定义模板(可以直接访问该类)。
最好的方法是什么?干杯
Answers:
您需要做三件事:
index.php
。myroute
和myargument
,以便WordPress不在查询字符串中出现时将其忽略。首先,我将建议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
。
添加查询变量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的上述操作,请执行以下操作:
像这个问题的原始发布者一样,我想创建一个自定义重写,并为该重写页面提供一个自定义模板。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' ) );
add_rewrite_endpoint
,它将为您生成规则并一次性添加查询var。另外,如果您要添加自己的重写规则,则建议使用此add_rewrite_rule
功能,而不要使用filter rewrite_rules_array
。
my_insert_rewrite_rules
顺序定义的规则!首先从最长的规则开始,然后逐步简化,否则/ api / myroute将覆盖/ api / myroute / myargument。