【问题标题】:It is possible to create any application using header() without output buffering [closed]可以在没有输出缓冲的情况下使用 header() 创建任何应用程序 [关闭]
【发布时间】:2014-07-01 23:43:42
【问题描述】:

每次我在 PHP 中创建网站或应用程序时,我都必须使用 header() 函数将人们从一个页面重定向到另一个页面,但是由于典型的标题几乎总是在我发现自己不得不使用减慢输出缓冲函数之前发送这页纸。要么就是这样,要么抑制“标头已发送”错误。我真的找不到任何可以在 PHP 中构建应用程序而不必违反两者的示例。

我想了解更多,关于一些如何在不使用输出缓冲的情况下重定向到页面。

编辑

这是一些人认为可能的。

<?php
$stack_errors = NULL;
if($_POST && isset($_POST['username']) && isset($_POST['password'])){

 $stmt = $pdo->prepare('SELECT * FROM users where username = ? AND password = ?');
 $stmt->execute(array($_POST['username'], $_POST['password']);
 if($stmt->rowCount() == 0){
   $stack_errors = 'error, username or password is incorrect';
 }else{
   $stack_errors = false; 
 }
}else{
  $stack_errors = 'please enter username and password to log in';
}
if(false === $stack_errors){
  header('Location: /success.php');
  exit;
}
?>
<html> 
<head></head>
<body>
<form>
 <input ...>
 <input ...>
 <?php if($stack_errors){
   echo $stack_errors; 
 }
<form>

【问题讨论】:

  • 是的,这是可能的,只是在任何事情之前发送标题
  • 相信我们,这是可能的。除非您无法控制代码,并且您被雇用只接触一小部分代码。为什么不提供示例代码?
  • 请注意,抑制“标头已发送”错误并不能解决问题。即使您禁止显示该消息,您的自定义标头仍将被忽略,因为发送它为时已晚。
  • 如果您的 header() 调用位于文件开头的 &lt;?php 块中,则项目的大小并不重要。听起来您是在说您的示例代码没有显示问题,所以仍然不清楚您到底遇到了什么问题。
  • 你问过怎么做,人们告诉你怎么做,你说“不,这不可能”。如果您确信在header() 调用之前无法避免输出,那么请删除您的问题(因为它没有可能的答案)并停止浪费每个人的时间。

标签: php


【解决方案1】:

一个编写良好的应用程序不应该存在“过早”发送输出并导致 PHP 发出 HTTP 标头的问题:

首先,可能导致重定向的决策应该发生在处理输入和做出业务决策期间;在将任何内容输出到页面之前,此代码应完全完成。这确保您的类和函数具有单一职责,并允许您 - 至少在理论上 - 无需重写整个应用程序即可替换输出,例如创建机器可读的 API 版本。与您的 cmets 不同,当您从事大型项目时,这一原则的重要性增加

其次,PHP 本身可能会输出错误和警告,但应该在生产系统上使用display_errors ini 设置将其关闭。你不希望用户看到你代码中每个错误的血腥细节——充其量,他们会做出判断;在最坏的情况下,他们会调查它是否存在安全漏洞。

第三,其他人指出了 PHP 标记之外的杂散空白以及编辑器添加的 Unicode BOM 的问题。这些可能很难追踪,但绝不是不可能的 - 一个体面的编辑器将具有显示空白和在没有 BOM 的情况下保存的功能。不使用结束符?&gt; 可以避免尾随空格,因为它隐含在文件末尾。使用gzip“输出过滤器”也会吞掉少量输出;这不会缓冲整个输出,但会一次缓冲几个字节,因此它有一些要压缩的东西,所以给你一点解脱。

【讨论】:

  • 感谢解答,但是这里没有一行支持your claim
  • @spartak 我完全不知道您希望看到什么证据。我只能从我的回答中重复这句话,这是设计一个好的 Web 应用程序框架的关键部分:“可能导致重定向的决定应该发生......在任何内容输出到页面之前”。何时输出内容取决于您,因此您可以自行设计应用程序以将逻辑与显示分开。
  • 我认为他想要的是有人给他准备好的代码,以便他可以轻松使用它,因为他无法从已经这样做的许多开源框架中理解它.
  • @Prix 问题在于这是不可能提供的,因为它是代码的缺失,而不是一个神奇的功能:我可以编写任何我喜欢的代码,只要它没有使用echo 或类似的,这将是一个没有输出任何东西的代码示例。在它的最后,我可以添加一个header() 调用,并保证不会从中得到错误。
  • @spartak 这些是 PHP cmets;他们不产生任何输出或标题。作为I suspected,您似乎认为只是运行代码——或者,在这种情况下,跳过 cmets——会导致 PHP 产生输出。事实并非如此,除非该代码明确使用 echo?&gt; 或其他一些其明确作用是向页面输出内容的函数。
【解决方案2】:

仅当您的 PHP 页面产生输出时才会发送标头。如果您的文件立即&lt;?php 块开头(之前没有空格、Unicode BOM 等),那么在您有机会设置自定义标题之前它不会产生任何输出。

如果您的代码在设置标头之前包含/需要任何其他 PHP 文件,请确保这些文件也不会产生任何不需要的输出。即使您的包含文件只是一个大的&lt;?php 块,请检查开头的空格/BOM 以及结尾的空格(例如?&gt; 之后的换行符)。

【讨论】:

  • 更不用说(肉眼不可见的)字节顺序标记,它也算作输出、cookie 等。这个主题太宽泛,很多人都会犯这些常见错误。
  • 好点子,注意你的编辑器将 BOM 放在文件的开头。 (由于 PHP 不支持 Unicode,因此 PHP 页面不应该有 Unicode BOM。)
  • 确保将文件另存为 ASCII 格式,而不是 UTF-8 或 UTF-16(可能标记为“Unicode”)。
  • 可以通过启用 gzip 压缩来解决 BOM 或少量杂散空白,它会缓冲输出,直到它有足够的时间启动压缩流。
  • 但是 BOM 不应该在那里。如果是输出,则表示它正在发送到浏览器,浏览器可能会误以为响应是 Unicode,而实际上它是别的东西。
【解决方案3】:

当然,HTTP 协议中的标头在响应中作为第一个发送。这就是它被称为“标题”的原因。您必须在代码逻辑中确保在任何其他输出之前发送标头。如果您想在决定发送哪些标头之前处理和输出任何数据,那么除了输出缓冲之外别无他法。然后 PHP 会为您完成这项工作。一旦确定不再发送标头,您就可以刷新并结束输出缓冲。

【讨论】:

    猜你喜欢
    • 2017-07-16
    • 2012-06-05
    • 1970-01-01
    • 2016-07-09
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 1970-01-01
    相关资源
    最近更新 更多