【问题标题】:How do I redirect with PHP if a header has already been sent?如果已发送标头,如何使用 PHP 重定向?
【发布时间】:2012-06-14 14:30:23
【问题描述】:

在 PHP 中重定向到不同页面的规范方式(据我所知)是这样的:

header("Location: URL");
exit();

但是让我们假设我需要在部分页面呈现后重定向。我习惯使用 ASP.NET,我可以在任何我想要的地方执行此操作

Response.Redirect("URL");

但我不知道如何在 PHP 中做一些等效的事情。是否可以?如果是,如何,如果不是,为什么不呢?

【问题讨论】:

  • 你应该改变你的逻辑:在你将用户发送到其他地方之前,不需要输出数据 0.1 秒。

标签: php http redirect


【解决方案1】:

使用 header 函数是不可能的,因为它的目的是发送 headers(不仅是为了重定向用户),而且当输出开始时你不能这样做,因为太晚了

一个快速的解决方法是为此使用 javascript,但这不是一个“优雅”的解决方案,更不用说如果访问者禁用了 javascript 或 javascript 代码中的某些错误导致问题,它就不起作用。

我认为确保您可以随时重定向的最佳方法是确保在脚本完成之前不呈现任何输出。为此,您至少应该使用一个模板引擎来确保您将 php 代码与 html 分开,并且在最后将内容发送给用户。

您还可以使用输出缓冲,因为这样您可以延迟输出被触发的时刻(当输出缓冲区大小超出或您自己刷新时;请参阅php.net/ob_start 了解这一点;您需要做类似的事情对此:http://codepad.org/AomD4Sok)

PS:不要忘记重定向后死/退出,不管你怎么做

【讨论】:

    【解决方案2】:

    或者,您可以使用 html 重定向来重定向页面。

    <meta http-equiv="refresh" content="0; url=xxx.php?page=2">
    

    但是,页面在重定向页面之前在此行上等待了大约 1 秒。

    (对不起朋友们。我的英语不太流利:(()

    我希望这些信息对您的业务有所帮助。

    【讨论】:

      【解决方案3】:

      理想情况下,您应该重新安排您的代码,以便重定向只能在发送任何标头之前发生。但如果你不能,你可以将所有内容存储在缓冲区中,并在所有内容完成后发送到浏览器:

      ob_end_clean();
      header('Location: xx');
      

      您可能需要在脚本顶部添加ob_start();

      我本来不同意 JS 解决方案,但在这个时代,我希望它会没事的。

      【讨论】:

        【解决方案4】:

        我建议将 url 存储在一个变量中,并在最后重定向。在此过程中,您也不应发送任何内容,而是将其存储并在最后发送,以确保您不会收到“标头已发送”错误。

        $url = '/posts';
        
        // code code code
        // oops, we want to redirect elsewhere now
        $url = '/tags';
        
        // end of script, send *content* and headers
        header("Location: $url");
        

        显然这里有很大的改进空间,但你明白了。在您的请求完成之前不要发送标头或内容。

        【讨论】:

        • 您不能在内容 (1) 之后发送标头字段。此外,要使 Location 产生任何效果,您需要发送 3xx 状态代码,这意味着您需要在开始发送响应之前知道。 (1) 除了使用“预告片”,普通UA不支持。
        • 我不确定我是否理解你。我在这里只是说脚本完成后应该发送响应(标题和所有)。这应该包装在一个类中并在一种调度过程中处理,但帖子的重点是说“存储你想要发送的内容并在脚本准备好时发送它,包括正确呈现内容。”
        【解决方案5】:

        在页面开头添加: ob_start(); 开始缓冲或在配置文件中启用缓冲。然后,您输出的所有内容都将“等待”脚本完成或刷新缓冲区:ob_flush。

        所以:

        ob_start();
        //something
        ob_end_clean(); //erase output
        header('Location: ');
        

        【讨论】:

          【解决方案6】:

          您可以实现自己的 Response 类,其语义与您习惯的类似,并使用它的实例来累积要作为响应发送的输出,而不是依赖 PHP 的默认行为,即在任何地方打印任何内容你希望。通过这种方式,您可以控制何时发送响应(以及标头)。这就是许多 PHP 框架实际上所做的事情——您可能想四处看看,看看是否可以选择一个适合您的框架,而不是使用原始 PHP。

          【讨论】:

            猜你喜欢
            • 2011-04-24
            • 1970-01-01
            • 1970-01-01
            • 2011-04-17
            • 1970-01-01
            • 1970-01-01
            • 2016-05-18
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多