【问题标题】:How can I trim my URL如何修剪我的网址
【发布时间】:2014-06-08 08:08:48
【问题描述】:

一个删除链接指向另一个页面,调用一个函数,如果函数成功,然后我将用户返回到他们单击删除的页面。

我用这个返回:

if ($booking->deleteBooking($_GET['id']))
{
    header('Location: ' . $_SERVER['HTTP_REFERER']);
}

我的链接看起来像这样:

/calendar.php?id=1&month=04&day=25&year=2014&t=11&v=true&f=true&reserved=true

当&reserved=true被发回时,我可以修剪链接并删除它吗?

【问题讨论】:

  • 你试试 str_replace()
  • 试试str_replace('&reserved=true','',$_SERVER['HTTP_REFERER'])
  • @rennyrocha: 如果reserved 是查询字符串中的第一个参数怎么办?如果它的值为truexyz呢?
  • @eggyal,问题是关于仅删除该代码..

标签: php explode


【解决方案1】:

我建议您避免使用 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 将总是比花时间复制意大利面编码更快。封装您的代码(在类或函数中),当您需要重构时,有时间出去享受现在和未来的天气。

【讨论】:

  • +1 所有优点。但是请注意,如果$this->url 不包含查询字符串,list($url, $query) = explode('?', $this->url, 2) 将触发错误:explode() 的结果将是一个单元素数组,不能分配给 2 元素 list()。虽然这可能不是不可取的(毕竟,人们试图删除不存在的参数),但它与尝试从存在的查询字符串中删除不存在的参数时的行为不一致。
  • @eggyal 谢谢,很好。我用来测试的在线模拟器由于某种原因没有标记那个模拟器。我有点假设当开发人员想要从 URL 中删除单个参数时……他们很确定至少存在一个查询字符串。也就是说,考虑到使用 HTTP_REFERER 的意图,我想我不应该假设任何事情。哈哈,我喜欢你的 parse_url / http_build_url 解决方案的弹性解决方案,实际上是上周为我自己的问题写的,但为了避免安装而重写了它。懒惰……可能。感谢您的支持!
  • 同意:在这种特殊情况下,这种极端情况不太可能受到影响,但如果您正在开发此类用于更通用的目的......
  • @eggyal 哦,同意。你是对的,我应该对冲它。我所做的只是开发通用代码了。哈哈,一旦我意识到同样的问题经常重复发生……我开始有点痴迷于封装我的代码。在这种情况下,我什至可能会使用诸如 has_query_string(url) 或 before(needle, haystack), after(needle, haystack) 之类的辅助函数……但我离题了。我在示例代码中针对“无查询字符串”存在问题进行了快速修复。不是很健壮...默默地“成功”,但我会将用例和期望的调整留给最终用户。再次感谢!
【解决方案2】:

建议您使用 PHP 的 URL functions 来解析 HTTP_REFERER 标头并进行相应调整,而不是执行可能容易出错的字符串操作:

// parse the referrer
$referer = parse_url($_SERVER['HTTP_REFERER']);

// parse the querystring part
parse_str($referer['query'], $querystring);

// unset the reserved parameter (only if value is 'true'?)
if ($querystring['reserved'] === 'true') unset($querystring['reserved']);

// reconstruct the revised querystring
$referer['query'] = http_build_query($querystring);

// redirect to the adjusted URL
header('Location: ' . http_build_url($referer));

【讨论】:

    【解决方案3】:

    使用 preg_replace

     preg_replace('/^&reserved=true/', '', $_SERVER['HTTP_REFERER']);
    

    【讨论】:

    • Remove ^ 和那个will work.
    • 如果reserved 是查询字符串中的第一个参数怎么办?如果它的值为truexyz呢?
    • 这个字符串最初是如何构建的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多