我建议您避免使用 regex 和 str_replace,因为当您的 URL 结构发生变化时,它们会很快失效。
我现在会把它放在一个类中,因为这不是你最后一次需要这样做(我上周才不得不这样做)或其他一些与 URL 相关的事情。因此,您应该立即将功能封装在一个地方,而不是以后。如果您找到更好或更正确的方法来处理任务,您可以随时在以后在一个地方更改实现。
关于您的脚本和可能的解决方案的一些相当重要的警告...
HTTP_REFERER 不能真正依赖。浏览器不需要发送它,很多都不需要。您可以通过自己在查询字符串中发送 URL(正确转义)或可能通过隐藏的表单字段来解决此问题。否则,您的重定向和脚本在很多情况下都会失败!见HTTP Referer not always being passed
如果您想要立即重定向,您应该始终在发送 Location 标头后退出...否则您的脚本将继续愉快地做事。 (数据库查询等)为此,我还将封装您的重定向代码,并在我的示例解决方案中这样做。
http_build_url 在 PHP 中默认不可用。这是一个 pecl_http 的事情。最终,在这种情况下它并不是真正需要的,我的示例解决方案在没有它的情况下也可以工作。
示例类用法:
$referrer = 'http://example.com/calendar.php?id=1&month=04&day=25&year=2014&t=11&v=true&f=true&reserved=true';
$url = new URL($referrer);
$url->remove_param('reserved');
$url->redirect();
类代码:
class URL
{
public $url = '';
function __construct ($url)
{
$this->url = $url;
}
function redirect ($response_code = 301)
{
header('Location: ' . $this->url, true, $response_code);
exit;
}
function remove_param ($param)
{
// Do nothing to URL without a Query String (hat tip @eggyal)
if (strpos($this->url, '?') === false) return $this->url;
// Split URL into base URL and Query String
list($url, $query) = explode('?', $this->url, 2);
// Parse Query String into array
parse_str($query, $params);
// Remove the parameter in question
unset($params[$param]);
// Rebuild Query String
$query = http_build_query($params);
// Piece URL back together and save to object
$this->url = $url . ($query ? "?$query" : '');
// Return URL in case developer really just wants an instant result
return $this->url;
}
}
警告:这不会保留任何 URL 片段(即#fragment) 对于 HTTP_REFERER,这应该无关紧要,因为大多数浏览器无论如何都不会发送它。如果这是您决定需要的功能,那么以后可以轻松地对其进行编码。
命名空间:为简单起见,代码示例没有命名空间。但是,对于现实生活中的实现,我建议养成使用“命名空间应用程序”的习惯;在任何内部类文件的顶部,并将类称为“new App\Class();”特别是如果您在项目中使用或可能曾经使用任何第三方代码。
性能说明:在出现问题之前不要担心性能...您的时间始终是最大的瓶颈...而不是 PHP。比 PHP 的时间更珍惜你的时间! PHP 将总是比花时间复制意大利面编码更快。封装您的代码(在类或函数中),当您需要重构时,有时间出去享受现在和未来的天气。