【问题标题】:Should I handle redirection via PHP or Javascript?我应该通过 PHP 还是 Javascript 处理重定向?
【发布时间】:2013-06-21 11:50:32
【问题描述】:

我正在重构一些旧代码并试图更好地理解headers。

我在No output before sending headers! 的以下帖子中读到了一个很棒的答案 现在我明白了“为什么”,但在实施时仍然有点模糊。

当点击取消按钮并搜索到值时,我的当前页面会重定向回来。

我存储发出请求的页面和会话变量中的值,允许我这样做:

if (isset($_SESSION['searchPage'])){
 header('Location:searchForm.php?ticket='.$_SESSION['product'].'&searchbtn=Search');
 exit();
}

但是,要在显示页面中进行这项工作,我必须使用 ob_start()。

为了避免这种解决方法,我发现我可以通过 javascript 重定向:

if (isset($_SESSION['searchPage'])){
    echo '<script>window.location="searchForm.php?product='.$_SESSION['product'].'&searchbtn=Search";</script>';    
    exit(); 
}

现在回答我的问题

  1. 哪种方法更好或可以接受?
  2. 我似乎想不出在使用header() 之前不发送任何输出的地方设计我的页面的方法。如果按钮单击事件导致重定向,您如何在不使用 ob_start() 的情况下处理 php 中的重定向?

【问题讨论】:

  • PHP。总是 PHP。使用 ob_start()(和其他 ob_* 函数)很好
  • “我似乎想不出一种方法来设计我的页面,使其在使用 header() 之前不发送任何输出。” – en.wikipedia.org/wiki/IPO_Model

标签: php javascript redirect header


【解决方案1】:

编辑
首先,您可能需要阅读更多关于使用header 进行重定向的内容。不只是设置header('Location:...');,而是使用以下代码重定向:

header ('HTTP/1.1 301 Moved Permanently');
header('Location:searchForm.php?ticket='.$_SESSION['product'].'&searchbtn=Search');

301 重定向通常更适合 SEO,并且大多数浏览器都会缓存重定向,因此客户端历史堆栈会更可靠,这对于可能使用历史记录的 JS 脚本来说是个好消息...

  1. 哪种方法更好?

PHP。仅仅依靠 JS 来重定向客户端并不是一个好主意。不是。客户可能会关闭您的脚本,或者如果 JS 代码中出现一些错误,重定向将不起作用。一些无聊的青少年可能会想弄乱您的代码,并在您的网站中发现可能存在的安全问题。

   2. 如何使用ob_*,或者如何在没有ob_* 的情况下使用header?

只需使用 ob_start() 调用启动您的输入脚本 (index.php),以确保。也许使用ob_implicit_flush(true),隐式刷新你的输出缓冲区。但更重要的是,只需在设置标题后立即调用ob_flush()。
或者考虑使用像 Symfony2 和/或 ZendFW 这样的框架。处理重定向的代码已经为你编写了很多次,为什么不使用它呢?

如果您想避开输出缓冲,也许您可​​能需要考虑遵循某些模式或设计原则(如 MVC、IPO 等)并将您的代码写入 (+-) 始终 em> 按照这个顺序处理业务:

  • 获取请求
  • 处理请求中的数据,确定客户端要求的数据
  • 结构数据
  • 渲染页面
  • 发送回复

在您处理完请求后,您就可以进行重定向,而且由于您甚至还没有接近呈现输出,更不用说发送标头了,您可以安全地重定向和/或设置标头...

更新:
只是一个链接以回应您可能想阅读的后续问题Gruyere has a special secion on XSS attacks...虽然我相信该文档的主要目的是如何安全地使用混搭(实际上是真正的 XSS 注入)。无论如何,他们在解释为什么以及如何使用 JS 来破坏任何 web 应用程序的安全性方面做得更好。

【讨论】:

  • 感谢您的详细回答。你说得对。我可能确实需要更多地了解标题。
  • 只是一个后续问题,在开发网站时,您是否应该始终考虑到用户可能在关闭 js 的情况下浏览?特别是随着 jQuery 的出现..
  • @codingUnderdog:这一切都取决于,真的......你关心大约 2% 的客户吗?如果没有,只需包含一个noscript 位,通知他们并非您网站的所有功能都可供他们使用。在某种程度上,这也将这些客户考虑在内。但是,当涉及到重定向时,我主要关心的是:JS 对客户端是开放的,他们可以看到(并操纵)重定向它们的代码。 XSS 攻击已经存在 20 年了,而且它们并没有变得更难实施。因此,作为开发人员,您应该永远不要信任网络。保持服务器端
  • ... 是一种控制事情的方法(或更多/更好地控制它们)
【解决方案2】:

在服务器端做总是更好。从 SEO 的角度来看,如果用户禁用了 JavaScript,或者下载您的 JS 文件时出现问题,或者其中存在导致停止执行的错误,JavaScript 会重定向。

【讨论】:

  • SEO 参数需要 301 重定向,OP 目前正在使用 HTTP 302 重定向(暂时移动)... Google 更喜欢 301
  • 我的意思是任何重定向。搜索引擎会选择服务器端重定向,但可能不会选择客户端。
  • Well, googlebot might,他们从事这项工作已经很多年了,而且他们确实接受了 JS 重定向……但总的来说,你是对的(只是认为你介意发现这篇文章很有趣,和我一样)
【解决方案3】:

PHP 重定向是最好的。因为即使用户在他的浏览器中禁用了脚本。

如果您使用的是 noscript 重定向,那么您可以使用 JS 而不是 PHP,这样在这种情况下您可以避免使用 ob_start()。

【讨论】:

    【解决方案4】:

    如果您只想通过单击按钮将用户发送到另一个页面,为什么不只是实现一个链接:

    <a href="searchForm.php?ticket=<?=$product?>&searchbtn=Search">go back</a>
    

    或按钮:

    <button onclick="window.location='searchForm.php?ticket=<?=$product?>&searchbtn=Search'">go back</button>
    

    【讨论】:

    • 这并不能解决 OP 的问题......这是一个关于设置标题的问题,这只是一种解决方法(而且不是一个非常用户友好的解决方法)
    • @EliasVanOotegem 该解决方案看起来设计过度。与其尝试修复它,为什么不建议一个不同的?
    • IMO,如果 OP 想要了解某些内容,那就是答案应该解释的内容。其次,会话通常是这样使用的:将您重定向到您上次浏览的最新搜索结果(或产品组)的网上商店很常见,恕我直言,如果我被要求点击它会感觉很笨拙恢复我的会话的链接,而不是单击链接返回主页。好吧,那只是我
    • 谢谢哥们。我得到了你的恕我直言。但我仍然坚信执行 2 个请求而不是 1 个请求是个坏主意。
    • 不确定我是否完全理解您的观点。我的回答基于问题“当单击取消按钮并搜索值时,我的当前页面重定向回来”中的这句话。据我了解,他想在按钮单击时显示另一个页面。从技术上讲,重定向只是一个迫使浏览器再发出一个请求的标头。在这种情况下,我认为这是一种开销。
    【解决方案5】:

    我建议采用以下方法:

    function universal_redirect($url, $force_js = false) {
        if (headers_sent() || $force_js) {
            print('<script type="text/javascript">');
            printf("location.href='%s';", $url);
            print('</script>');
        } else {
            header('Location: ' . $url);
        }
    }
    

    它并不总是适用,但如果您构建管理页面或当您的项目足够大且足够复杂以至于您不能总是保证输出尚未开始时,它是一个很好的解决方案。

    一般来说,由于@Elias Van Ootegem 给出的原因,PHP 重定向要好得多。

    【讨论】:

    • and 也不关心 not 使用 JS 的参数吗?也懒得理解标题?如果是这样,你为什么不直接回答“为什么要问这个问题?”
    • 我同意你的理由。虽然这个解决方案也有一些应用。更正了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 2016-08-04
    • 2019-06-09
    • 2019-04-01
    相关资源
    最近更新 更多