我试图动态添加一个重写规则,允许用户访问我选择的另一个永久链接结构下的任何页面。
例如,如果交替permalink结构包括段塞foo/
在第一个帖子中,我想添加一个重写规则,以便:
example.com/foo/my-page
重写到example.com/my-page
example.com/foo/my-cool/blog/post
重写到example.com/my-cool/blog/post
因此,基本上,无论查询是针对页面、帖子还是任何其他类型的自定义内容,我都希望在/foo/
slug以及原始的非foo URL结构。
我已经编写了一个工作函数,它通过..来实现这一点。。
读取URI从URI中删除段塞,遍历所有现有重写规则,将URI与删除的段塞匹配到现有重写规则,获取匹配组以匹配重写规则将其值作为目标以下是代码:
// functions.php
add_filter(\'rewrite_rules_array\', function($rules) {
$slug = \'foo\';
// get the request URI
$uri = $_SERVER[\'REQUEST_URI\'];
// determine whether URI has slug in the first position
if(preg_match(\'/^(\\/\' . $slug . \')/\', $uri)){
// get the base URI by removing the slug
$base_uri = str_replace(\'/\'.$slug,\'\',$uri);
// loop through existing rewrite rules
foreach($rules as $src => $dest){
// find the rewrite rule for which the base URI would have matched
$regex_to_match = \'/\' . str_replace(\'/\',\'\\/\',$src) . \'/\';
preg_match_all($regex_to_match, $base_uri, $matches, PREG_SET_ORDER);
if(count($matches) > 0){
// get the specific matching groups
$matches = $matches[0];
// compile valid regex from URI with slug to create new rewrite source
$new_src = ($uri[0] == \'/\' ? substr($uri, 1) : $uri) . \'?$\';
// replace match variables with their string values to create new rewrite destination
for($i=1; $i<count($matches)+1; $i++){
$replacement = isset($matches[$i]) ? $matches[$i] : \'\';
$dest = str_replace(\'$matches[\' . $i . \']\', $replacement, $dest);
}
$new_dest = $dest;
// add new rewrite rule to $wp_rewrite rules array
$rules[$new_src] = $new_dest;
// add the write rule
add_rewrite_rule($new_src,$new_dest,\'top\');
break;
}
}
}
return $rules;
});
flush_rewrite_rules();
这可以工作,但仅适用于具有多个段塞的URL。
example.com/foo/my-page/123
正确重写!
example.com/foo/abc/defg/bar
正确重写!
example.com/foo/abc
DOES NOT 正确重写。而是重定向到example.com/abc
与相同example.com/foo/my-page
-- 它重定向到example.com/my-page
SO网友:brianjohnhanna
更新代码的问题在于add_rewrite_rule()
在过滤器内部,它无法将其正确添加到列表的顶部。如果您将$rules
大堆因为它被添加到$rules
列表中,WP提前介入,在后台使用一些魔法单独匹配slug。
为了绕过这个过程,您必须手动将其添加到列表的顶部,并从过滤器返回。
具体来说,您需要更改add_rewrite_rule()
调用此:
$rules = [$new_src => $new_dest] + $rules;
我在下面包含了完整的更新代码。
add_filter(\'rewrite_rules_array\', function($rules) {
$slug = \'foo\';
// get the request URI
$uri = $_SERVER[\'REQUEST_URI\'];
// determine whether URI has slug in the first position
if(preg_match(\'/^(\\/\' . $slug . \')/\', $uri)){
// get the base URI by removing the slug
$base_uri = str_replace(\'/\'.$slug,\'\',$uri);
// loop through existing rewrite rules
foreach($rules as $src => $dest){
// find the rewrite rule for which the base URI would have matched
$regex_to_match = \'/\' . str_replace(\'/\',\'\\/\',$src) . \'/\';
preg_match_all($regex_to_match, $base_uri, $matches, PREG_SET_ORDER);
if(count($matches) > 0){
// get the specific matching groups
$matches = $matches[0];
// compile valid regex from URI with slug to create new rewrite source
$new_src = ($uri[0] == \'/\' ? substr($uri, 1) : $uri) . \'?$\';
// replace match variables with their string values to create new rewrite destination
for($i=1; $i<count($matches)+1; $i++){
$replacement = isset($matches[$i]) ? $matches[$i] : \'\';
$replacement = strpos($replacement, \'/\') === 0 ? substr($replacement, 1) : $replacement;
$dest = str_replace(\'$matches[\' . $i . \']\', $replacement, $dest);
}
$new_dest = $dest;
// add new rewrite rule to $wp_rewrite rules array
$rules = [$new_src => $new_dest] + $rules;
break;
}
}
}
return $rules;
});
这样做仍然感觉很奇怪,我相信还有更好的方法,但如果不更好地理解您的用例,我真的无法提供其他建议。对我来说,这里最大的问题是您正在刷新每个请求的重写规则,这可能是一个昂贵的操作。
测试了以下内容,可用于重定向http://example.com/foo/test/123 到https://example.com/test/123. 可以根据您的需要进行定制。将其放入函数中。php或功能插件。
add_action( \'init\', function() {
add_rewrite_rule( \'foo/([a-z0-9-/]+)[/]?$\', \'index.php?foo_redirect_to=$matches[1]\', \'top\' );
} );
add_filter( \'query_vars\', function( $query_vars ) {
$query_vars[] = \'foo_redirect_to\';
return $query_vars;
} );
add_action(\'template_redirect\', function() {
if ( ( $redirect_to = get_query_var( \'foo_redirect_to\' ) ) == false ) {
return;
}
wp_redirect("https://example.com/$redirect_to");
});