@vidja 与redirect_canonical 非常接近,而且肯定在正确的轨道上。
我自己深入研究了这个问题,发现这是 PHP 本身和 WordPress 中的重定向逻辑之间的问题的组合。如果您直接查看 php 全局 $_GET,您会发现查询字符串参数被“错误地”解析的地方。例如:
// For a url like: /some/path/?tracking.id=123
var_dump($_GET);
// array(1) { ["tracking_id"]=> string(3) "123" }
如果你继续挖掘redirect_canonical代码,你最终会发现罪魁祸首是一堆函数调用,以php的parse_str方法结束:
// https://developer.wordpress.org/reference/functions/_remove_qs_args_if_not_in_url/
_remove_qs_args_if_not_in_url()
// https://developer.wordpress.org/reference/functions/remove_query_arg/
remove_query_arg()
// https://developer.wordpress.org/reference/functions/add_query_arg/
add_query_arg()
// https://developer.wordpress.org/reference/functions/wp_parse_str/
wp_parse_str()
// https://www.php.net/manual/en/function.parse-str.php
parse_str()
直接测试parse_str 会得到与查看$_GET 相同的结果:
$arr = [];
parse_str('tracking.id=123', $arr);
var_dump( $arr );
// array(1) { ["tracking_id"]=> string(3) "123" }
所有这一切都说明有一种更好的方法来设置您自己的过滤器,以便您获得更强大的结果。例如,@vidja 编写他的过滤器的方式会导致页面在您希望的时候无法正确重定向(因此,WordPress 会显示 404 not found 页面)。假设您有一个带有/sample-page slug 的页面,并且您尝试通过以下网址访问您的网站:/sampl?tracking.id=123。 Wordpress 想要将其重定向到/sample-page/?tracking_id=123,但@vidja 的代码将改为返回原始(错误)url,因为tracking_id 设置在$_GET 中。因此,在我看来,处理这个问题的更好方法是替换您在重定向 url 中关心的特定查询字符串参数,这样 Wordpress 可以按照它认为合适的方式重定向页面,但您也可以维护你的tracking.id 正确。这就是它的样子:
add_filter( 'redirect_canonical', function ( $redirect_url, $requested_url ) {
return preg_replace( '/tracking_id=/', 'tracking.id=', $redirect_url );
}, 10, 2 );
如果您有多个带有句点的查询字符串参数需要维护,您甚至可以执行以下操作:
add_filter( 'redirect_canonical', function ( $redirect_url, $requested_url ) {
$query_params = [
'tracking_id' => 'tracking.id',
'foo_bar' => 'foo.bar',
];
foreach ( $query_params as $search => $replace ) {
$redirect_url = preg_replace( '/'.$search.'=/', $replace.'=', $redirect_url );
}
return $redirect_url;
}, 10, 2 );