我有以下规则来检查 url 是否包含任何以 p2
开头的参数:
function unparse_url($parsed_url) {
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
$user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
$pass = ($user || $pass) ? "$pass@" : '';
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
$query = isset($parsed_url['query']) ? '?' . trim($parsed_url['query'], '&') : '';
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
return "$scheme$user$pass$host$port$path$query$fragment";
}
function strip_query($url, $query_to_strip) {
$parsed = parse_url($url);
$parsed['query'] = preg_replace('/(^|&)'.$query_to_strip.'[^&]*/', '', $parsed['query']);
return unparse_url($parsed);
}
$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$new_url = (strip_query($url, 'p2'));
# redirect if url contains anything that starts with p2
$filtered = array_filter(array_keys($_GET), function($k) {
return strpos($k, 'p2') === 0;
});
if ( !empty($filtered) ) {
header ("Location: $new_url");
}
else {
}
如果 url 包含任何p2*
参数,则会重定向到没有这些参数的同一页面。
例:
domain.com/?a=3&p2=1
将重定向至
domain.com/?a=3
但是,使用当前规则,如果原始 URL 是:
domain.com/?p2=1
然后它将重定向到:
domain.com/?
但由于它毫无意义,我希望在这种情况下它将重定向到:
domain.com/
怎么能做到呢?
像@dontfight一样,我建议使用mod_rewrite但是如果您更喜欢PHP,则可以在执行重定向之前使用rtrim
rtrim($url, '?');
使用您的代码,您可以像这样使用
$filtered = array_filter(array_keys($_GET), function($k) {
return strpos($k, 'p2') === 0;
});
$new_url_trim = rtrim($new_url, '?');
if ( !empty($filtered) ) {
header ("Location: $new_url_trim");
}
else {
}
下面是删除查询参数的另一种方法:
- 分析 URL 以将其分为方案、路径和查询
- 将查询字符串解析为数组
- 取消设置数组中的参数
- 重新创建网址
例:
<?php
function removeQuery($url, $param) {
$parsed = parse_url($url);
parse_str($parsed['query'], $query);
unset($query[$param]);
$parsed['scheme'] .= '://';
$parsed['query'] = http_build_query($query);
if (!empty($parsed['query']))
$parsed['path'] .= '?';
return implode($parsed);
}
echo removeQuery('http://domain.com/?a=3&p2=1', 'a') . "'n";
echo removeQuery('http://domain.com/?a=3&p2=1', 'p2') . "'n";
echo removeQuery('http://domain.com/?p2=1', 'p2');
输出:
http://domain.com/?p2=1
http://domain.com/?a=3
http://domain.com/
我还注意到,如果p2
出现在字符串中的任何位置,您想删除它,因此这是另一个旨在执行此操作的版本:
<?php
function removeP2($url) {
$parsed = parse_url($url);
parse_str($parsed['query'], $query);
foreach ($query as $key => $value)
if (strpos($key, 'p2') === 0)
unset($query[$key]);
$parsed['scheme'] .= '://';
$parsed['query'] = http_build_query($query);
if (!empty($parsed['query']))
$parsed['path'] .= '?';
return implode($parsed);
}
echo removeP2('http://domain.com/?a=3&p2=1') . "'n";
echo removeP2('http://domain.com/?a=3&p2sks=1') . "'n";
echo removeP2('http://domain.com/?p2=1');
输出:
http://domain.com/?a=3
http://domain.com/?a=3
http://domain.com/
现在要让它重定向,您已经知道如何重定向:
header("Location: " . removeP2('http://' . $_SERVER[HTTP_HOST] . $_SERVER[REQUEST_URI]));
既然没有人费心告诉你出了什么问题......
您的问题是您的 strip_query()
函数总是将$url["query"]
设置为一个值,即使该值是空字符串:
$parsed['query'] = preg_replace('/(^|&)'.$query_to_strip.'[^&]*/', '', $parsed['query']);
当您的unparse_url()
函数获取 URL 时,它会使用 isset()
检查该数组索引,该索引始终传递:
$query = isset($parsed_url['query']) ? '?' . trim($parsed_url['query'], '&') : '';
您可以使用 empty()
代替检查isset()
,如果值未设置或为空字符串,它将返回 false:
$query = !empty($parsed_url['query']) ? '?' . trim($parsed_url['query'], '&') : '';
如果mod_rewrite可用,这可以在没有PHP代码的情况下完成。
这不是答案,而是评论,但有点长。
为什么你如此热衷于从URL中删除这个变量?它对你有什么伤害,你必须不遗余力地根除它的存在?为什么不只是...
unset($_GET['p2']);
但既然毫无意义,
以什么方式?
我可以看到unparse_url($parsed_url)
函数的一些优点,如果您修复错误(提示:尝试一些带有用户名和/或密码的测试用例(,那么它的结构相当良好 - 但随后用于操作数据的代码是正则表达式字符串拼接的混乱混合 - 这不是处理此类结构化数据的正确方法 - PHP 具有此功能。
但最糟糕的一点是注入另一个完整的 RTT 来解析 URL。
你比这个洛基罗比!