WordPress Rewrite Rules详解

WordPress Rewrite Rules是控制wordpress路由的,说简单点就是控制访问链接的。

一、可使用函数

1、add_rewrite_rule() 允许我们为 WordPress 添加自定义重写规则,通常和下面的add_rewrite_tag()配合使用。

add_rewrite_rule($regex, $redirect, $after);

$regex (string) (必需) 一个匹配请求 URL 的正则表达式,可是使用一个或多个正则表达式组。默认:None

$redirect (string) (必需):真正需要获取的 URL, ($regex 匹配时).。我们可以使用 $matches[] 数组在这里插入捕获获的匹配组。默认: None

$after (string) (可选):这可以是 ‘top’ 或 ‘bottom’.。’top’ 将在 WordPress 现有的规则之前优先处理, ‘bottom’ 将在其他规则之后处理。默认: “bottom”

2、add_rewrite_tag() 允许我们添加 WordPress 可以识别的自定义查询参数。

add_rewrite_tag($tag, $regex, $query);

$tag (string) (必需) 重定向标签的名称,开始和结尾需要用 % 包括起来。默认: None

$regex (string) (必需) 指定标签的正则表达式默认: None

$query (string) (可选) 附加查询到查询属性数组默认: None

二、使用例子

1、add_rewrite_rule()

访问链接:http://example.com/leaf/95

如同访问链接:http://example.com/index.php?page_id=95

add_action('init', function ()
{
    add_rewrite_rule('^leaf/([0-9]+)/?', 'index.php?page_id=$matches[1]', 'top');
});

2、add_rewrite_rule()和add_rewrite_tag()配合使用

页面:

query_vars['food'];
echo '
';
echo 'Variety : ' . $wp_query->query_vars['variety'];
// ... more ...
get_footer();
?>

add_rewrite_tag() (使用 add_rewrite_tag() 让 WordPress 可以识别自定义查询变量 「food」 和 「variety」):

add_action('init', function ()
{
    add_rewrite_tag('%food%', '([^&]+)');
    add_rewrite_tag('%variety%', '([^&]+)');
}, 10, 0);

add_rewrite_rule() (改变路由):

add_action('init', function ()
{
    add_rewrite_rule('^nutrition/([^/]*)/([^/]*)/?', 'index.php?page_id=12&food=$matches[1]&variety=$matches[2]', 'top');
}, 10, 0);

此时访问:http://example.com/nutrition/milkshakes/strawberry/

如同访问:http://example.com/index.php?page_id=12&food=milkshake&variety=strawberry

3、add rewrite tag 单独使用示例

下面的代码将注册一个名称为 ‘film_title’ 的查询标签:

<?php
function custom_rewrite_tag() {
add_rewrite_tag('%film_title%', '([^&]+)');
}
add_action('init', 'custom_rewrite_tag', 10, 0);
?>

获取重定向后的查询的参数值(这也就是2中为什么要和add rewrite tag一起使用):

$wp_query->query_vars['film_title']

国外网站的代码:

<?php
add_action( 'init', 'rewrite_tag_example_init' );
add_action( 'template_redirect', 'rewrite_tag_example_template_redirect' );
/**
 * Add rewrite rule and tag to WP
 */
function rewrite_tag_example_init(){
	// rewrite tag adds the matches found in the pattern to the global $wp_query
	add_rewrite_tag( '%affiliate%', '(.*)' );
}
/**
 * Modify the query based on our rewrite tag
 */
function rewrite_tag_example_template_redirect(){
	// get the value of our rewrite tag
	$affiliate = get_query_var( 'affiliate' );
	// check if our rewrite tag has value
	if ( !empty( $affiliate ) ){
		// track where this visitor came from
		setcookie( 'affiliate', $affiliate, 0, '/' );
	}
}

三、高级用法,使用hook新增、修改、删除路由

这里的话有两种类型的hook

1、这里和上面一样

function iteblog_rewrite_rule() {
  add_rewrite_rule('wechat$', 'index.php?iteblog_hadoop'', 'top');
}
add_action('init', 'iteblog_rewrite_rule');

2、高级用法,很多地方看到这类用法,适合用在复杂场景,hook的是rewrite_rules_array。

新增路由:

function add_rewrite_rules($aRules){
        $aNewRules = array(
                'wechat$' => 'index.php?iteblog_hadoop'
        );
        $aRules = $aNewRules + $aRules;
        return $aRules;
}
add_filter('rewrite_rules_array', 'add_rewrite_rules');

删除路由:

add_filter('rewrite_rules_array', 'kill_feed_rewrites');
function kill_feed_rewrites($rules){
 
    foreach ($rules as $rule => $rewrite) {
 
        if ( preg_match('/^foo.*(feed)/',$rule) ) {
            unset($rules[$rule]);
        }
 
    }
 
    return $rules;
}

修改路由可以参照删除路由改改,也可以先删除再新增。

更多hook:

<?php
add_action( 'init', 'rewrite_tag_permalink_init' );
add_action( 'pre_get_posts', 'rewrite_tag_permalink_pre_get_posts' );
// normal posts
add_filter( 'post_link', 'rewrite_tag_permalink_post_link', 10, 2 );
// custom post types
add_filter( 'post_type_link', 'rewrite_tag_permalink_post_link', 10, 2 );
/**
 * Add our rewrite rule and rewrite tag
 */
function rewrite_tag_permalink_init(){
	// rewrite rule looks for custom_folder
	add_rewrite_rule( '^([^/]+)/(.*)/?', 'index.php?custom_folder=$matches[1]&name=$matches[2]', 'bottom' );
	// rewrite tag puts custom_folder value into the query vars
	add_rewrite_tag( '%custom_folder%', '(.*)' );
}
/**
 * Alter permalinks to reflect the new custom_folder rewrite tag
 *
 * @param $permalink
 * @param $post
 *
 * @return mixed
 */
function rewrite_tag_permalink_post_link( $permalink, $post ) {
	$rewrite_tag = '%custom_folder%';
	// return early if tag not found
	if ( strpos( $permalink, $rewrite_tag ) === FALSE ) {
		return $permalink;
	}
	// look for custom permalink meta data
	$custom_folder = get_post_meta( $post->ID, 'custom_folder', true );
	// if a custom permalink exists as meta data, use it
	if ( !empty( $custom_folder ) ){
		$permalink = str_replace( $rewrite_tag, $custom_folder, $permalink );
	}
	// fallback by completely removing our tag from the permalink
	else {
		$permalink = str_replace( $rewrite_tag . '/', '', $permalink );
	}
	return $permalink;
}
/**
 * Use pre_get_posts to make the custom_folder meta data value  optional
 *
 * @param $query
 */
function rewrite_tag_permalink_pre_get_posts( $query ){
	if ( $query->is_main_query() ){
		// if only the first argument is presented, use it as the post name
		if ( get_query_var( 'custom_folder' ) &&
		     !get_query_var( 'name' ) )
		{
			// what we thought was the custom_folder is actually the post_name
			$query->set( 'name', get_query_var( 'custom_folder' ) );
			$query->is_home = false;
			$query->is_singular = true;
			$query->is_single = true;
		}
	}
}

四、特别说明

对于上面的一系列路由操作,在我们操作后,发现并不生效,有两种做法:

1、后台》设置》固定链接,(不要选择朴素类型,选个其他的),然后保存一下,就会刷新路由。

2、代码方式,其实做上面的操作是因为,操作一次就执行了这个代码:

flush_rewrite_rules();

或者下面的代码:

global $wp_rewrite;
$wp_rewrite->flush_rules();
© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享