How to fix “Headers already sent” error in PHP
在运行我的脚本时,我遇到了如下几个错误:
Warning: Cannot modify header information - headers already sent by (output started at /some/file.php:12) in /some/file.php on line 23
错误消息中提到的行包含
为什么会这样?如何修复?
发送邮件头之前没有输出!
在进行任何输出之前,必须调用发送/修改HTTP头的函数。摘要?否则呼叫失败:好的。
Warning: Cannot modify header information - headers already sent (output started at script:line)
Ok.
修改HTTP头的一些函数是:好的。
header /header_remove 。session_start /session_regenerate_id 。setcookie /setrawcookie 。
输出可以是:好的。
无意的:好的。
之前或 ?> 之后的空白- UTF-8字节顺序标记
- 以前的错误消息或通知
故意的:好的。
print 、echo 等产生输出的功能- 原
段先于 码。
为什么会这样?
要理解为什么在输出之前必须发送头,必须查看典型的HTTP反应。PHP脚本主要生成HTML内容,但也传递一个Web服务器的http/cgi头集:好的。
1 2 3 4 5 6 7 8 9 10 11 12 | HTTP/1.1 200 OK Powered-By: PHP/5.3.7 Vary: Accept-Encoding Content-Type: text/html; charset=utf-8 <html><head>PHP page output page</head> <body>Content <p> Some more output follows... </p>Ok. and <img src=internal-icon-delayed> |
页面/输出始终遵循标题。PHP必须通过首先指向Web服务器的头。它只能做到一次。在双断线之后,它永远无法修正它们。好的。
当php接收到第一个输出(
Warning: Cannot modify header information - headers already sent by
(output started at /www/usr2345/htdocs/auth.php:52) in
/www/usr2345/htdocs/index.php on line 100Ok.
这里"行100"是指
括号内的"输出开始于"注释更为重要。它指定了以前输出的源。在这个例子中,它是
典型原因:好的。
产生输出的函数包括好的。
print 、echo 、printf 、vprintf 。trigger_error 、ob_flush 、ob_end_flush 、var_dump 、print_r 。readfile 、passthru 、flush 、imagepng 、imagejpeg 。
以及用户定义的函数。好的。
1 2 3 | <!DOCTYPE html> <?php // Too late for headers already. |
使用模板方案将处理与输出逻辑分离。好的。
- 将表单处理代码放在脚本上。
- 使用临时字符串变量延迟消息。
- 实际的输出逻辑和混合的HTML输出应该紧随其后。
如果警告指的是 类似地,附加的脚本或脚本部分也会出现这种情况:好的。 PHP实际上会在关闭标记后占用一个换行符。但它不会补偿多个换行符、制表符或空格移动到这些间隙中。好的。
2
# There's a SINGLE space/newline before <? - Which already seals it.
2
3
<?php
换行符和空格本身就是一个问题。但也有"看不见的"可能导致这种情况的字符序列。最著名的是UTF-8 BOM(字节顺序标记)大多数文本编辑器都不显示。它是字节序列
特别是图形编辑器和基于Java的IDE是不被注意的。在场。它们不将其可视化(受Unicode标准的约束)。然而,大多数程序员和控制台编辑器都会:好的。
好的。
在那里,很容易及早发现问题。其他编辑可确定它出现在文件/设置菜单中(Windows上的记事本++可以识别和解决问题)。另一个检查boms存在的选项是使用hexeditor。on*nix系统通常提供
好的。
一个简单的解决方法是设置文本编辑器将文件保存为"UTF-8(无BOM)"。或类似的命名法。通常新来者都会选择创造新的文件,然后复制并粘贴上一个代码。好的。修正实用程序
还有自动工具来检查和重写文本文件(
1 | phptags --whitespace *.php |
整体上使用include或project目录是明智的。好的。
如果错误源在关闭
人们通常建议,尤其是对新来者来说,要跟踪
如果没有错误源,它通常是一个php扩展或php.ini设置。具体化。好的。
- 有时是
gzip 流编码设置或者是ob_gzhandler 。 - 但它也可以是任何双重加载的
extension= 模块。生成隐式PHP启动/警告消息。
如果另一个php语句或表达式导致警告消息或请注意,正在打印输出,这也算作过早输出。好的。
在这种情况下,您需要避免错误,延迟语句执行,或用例如
无错误消息
如果你的
所以当
1 2 |
或者,如果所有其他方法都失败的话,用
说到重定向头,您应该经常使用类似这样的成语对于最终代码路径:好的。
甚至是打印用户消息的实用程序函数如果
PHPS输出缓冲是缓解这一问题的一种解决办法。它通常工作可靠,但不应该替代适当的应用程序结构并将输出与控制分离逻辑。它的实际用途是最小化到Web服务器的分块传输。好的。
江户十一〔15〕号尽管如此,设置还是有帮助的。在php.ini中配置它或通过.htaccess甚至.user.ini打开现代fpm/fastcgi设置。启用它将允许PHP缓冲输出,而不是将其传递给Web服务器立刻。因此,PHP可以聚合HTTP头。好的。
它也可以拨打
即使
启动第一个脚本,空白或bom可能会被洗牌之前,使其无效。好的。 它可以为HTML输出隐藏空白。但是一旦申请逻辑尝试发送二进制内容(例如生成的图像),缓冲的外部输出成为一个问题。(需要EDOCX1[0]当弗尔赫在工作的时候。)好的。
缓冲区的大小是有限的,如果保留为默认值,则很容易溢出。这也不是罕见的,很难找到。当它发生的时候。好的。
因此,这两种方法都可能变得不可靠,尤其是在两种方法之间切换时开发设置和/或生产服务器。这就是为什么输出缓冲被广泛认为只是一种拐杖/严格来说是一种权宜之计。好的。
另请参见基本用法示例在手册中,为了获得更多的优点和缺点:好的。
- 什么是输出缓冲?
- 为什么在PHP中使用输出缓冲?
- 使用输出缓冲是否被视为一种坏做法?
- 输出缓冲的用例,作为"已发送邮件头"的正确解决方案
但它在另一台服务器上工作!?
如果之前没有收到头警告,那么输出缓冲PHPini设置改变了。它可能在当前/新服务器上未配置。好的。与
如果仍然有可能…发送标题。有条件地打印信息或应用其他回退逻辑。好的。
1 2 3 4 5 6 | if (headers_sent()) { die("Redirect failed. Please click on this link:"); } else{ exit(header("Location: /user.php")); } |
有用的回退解决方法是:好的。
- html
标记 如果您的应用程序在结构上很难修复,那么允许重定向的方法是注入一个HTML
标签。可通过以下方式实现重定向:好的。 1<meta http-equiv="Location" content="http://example.com/">或短暂延迟:好的。
1<meta http-equiv="Refresh" content="2; url=../target.html">当使用超过
部分时,这会导致无效的HTML。大多数浏览器仍然接受它。好的。 - javascript重定向
作为替代,JavaScript重定向可用于页面重定向:好的。
1location.replace("target.html");虽然这通常比
解决方案更符合HTML,它依赖于支持JavaScript的客户机。好的。
但是,当真正的HTTP头()时,这两种方法都会进行可接受的回退。呼叫失败。理想情况下,您总是将此与用户友好的消息结合在一起,并且点击链接作为最后手段。(例如,http_redirect()是什么)PECL扩展功能。)好的。为什么
(当然,它们还受到浏览器中禁用的cookie的影响,甚至代理问题。会话功能显然也依赖于自由磁盘空间和其他php.ini设置等。)好的。进一步环节
- 谷歌提供了一长串类似的讨论。
- 当然,在堆栈溢出中也涵盖了许多特定的情况。
- WordPress常见问题解答解释了如何解决已经发送的邮件头的警告问题?以一般的方式。
- Adobe社区:PHP开发:为什么重定向不起作用(头文件已经发送)
- Nucleus常见问题解答:"page headers already sent"是什么意思?
- 其中一个更深入的解释是http headers和php header()函数——Nicholassolutions(Internet存档链接)的教程。它详细介绍了HTTP,并给出了一些重写脚本的指导原则。
好啊。
在发送HTTP头(使用
意外的空白,通常在文件的开头或结尾,如下所示:
1
2
3<?php
// Note the space before"<?php"
?>
&为了避免这一点,只需将收市日期省略1(2)-无论如何都不需要。
- PHP文件开头的字节顺序标记。使用十六进制编辑器检查您的PHP文件,以确定情况是否如此。它们应该以
3F 3C 字节开始。您可以从文件开头安全地删除bomEF BB BF 。 - 显式输出,如调用
echo 、printf 、readfile 、passthru 、前的代码等。 - 如果设置了
display_errors php.ini属性,则由php输出的警告。PHP不会因为程序错误而崩溃,而是静默地修复错误并发出警告。虽然您可以修改display_errors 或错误报告配置,但您更应该解决该问题。
常见原因是访问数组的未定义元素(如$_POST['input'] ,而不使用empty 或isset 来测试输入是否已设置),或使用未定义常量而不是字符串文字(如$_POST[input] 中,注意缺少引号)。
打开输出缓冲会使问题消失;调用
但是,虽然输出缓冲可以避免这些问题,但是您应该真正确定应用程序在HTTP头之前输出HTTP主体的原因。那就像打电话,在告诉来电者他打错电话号码之前,先讨论一下你的一天和天气。
我以前多次遇到这个错误,我确信所有的PHP程序员至少都有一次遇到这个错误。要解决此错误,可以根据问题级别解决使用解决方案:
可能的解决方案1:
您可能在之前或之后(在之后的文件末尾)留下了空格。>)
1 2 3 4 5 6 7 | THERE SHOULD BE NO BLANK SPACES HERE <?php echo"your code here"; ?> DO CHECK FOR BLANK SPACES HERE AS WELL; THIS LINE (blank line) SHOULD NOT EXIST. |
大多数情况下,这可以解决您的问题。请检查与您的
注意:有时像gedit(一个默认的Linux编辑器)这样的编辑器(ide)会在保存文件时添加一个空行。这不应该发生。如果您使用的是Linux。您可以使用vi编辑器删除后面的空格/行吗?>在页面的末尾。
如果这不是您的情况,那么您可以使用ob_start进行输出缓冲,如下所示:
可能的解决方案2:
1 2 3 4 5 6 7 |
这将打开输出缓冲,并在缓冲页面后创建标题。
而不是下一行
1 | //header("Location:".ADMIN_URL."/index.php"); |
写
1 | echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';"); |
或
1 | ?><?php echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';");?><?php |
这肯定能解决你的问题。我也面临同样的问题,但我通过上面的方式写标题位置解决了这个问题。
你做
1 |
在设置cookie之前,这是不允许的。您不能在标题之前发送任何输出,即使是空行也不行。
这是因为这一行:
1 |
在发送邮件头之前,不应打印/回送任何内容。
常见问题:
(复制自:源)
(=)=
1)在
2)清除
3)黄金法则!-检查该php文件(以及,如果
4)在
5)始终使用301或302参考:
6)打开错误报告,并查找错误。您的错误可能是由一个不工作的函数引起的。当您打开错误报告时,您应该总是首先修复最顶端的错误。例如,它可能是"warning:date_default_timezone_get():依赖系统的时区设置是不安全的。"-然后向下看,您可能会看到"headers not sent"错误。修复最上面的(第一个)错误后,重新加载页面。如果仍然有错误,请再次修复最顶端的错误。
7)如果以上都没有帮助,那么使用jawscript重定向(但是,强烈不推荐的方法),可能是自定义情况下的最后一次机会…:
1 |
一个简单的提示:脚本中的一个简单的空格(或不可见的特殊字符)就在第一个
我见过这些东西;)
另一个不好的做法可能引发这个尚未说明的问题。
请参见以下代码段:
1 2 3 4 | <?php include('a_important_file.php'); //really really really bad practise header("Location:A location"); ?> |
一切都好吧?
如果"一个重要的文件.php"是:
1 2 3 4 5 6 7 | <?php //some php code //another line of php code //no line above is generating any output ?> ----------This is the end of the an_important_file------------------- |
这样不行?为什么?因为已经生成了新行。
现在,尽管这不是一个常见的场景,但是如果您使用的是一个MVC框架,它在将事情移交给控制器之前加载了大量文件,该怎么办?这不是一个罕见的情况。做好准备。
来自PSR-2 2.2:
- 所有PHP文件都必须使用
Unix LF (linefeed) line ending 。 - 所有PHP文件必须以
single blank line 结尾。 - 闭幕?>标签必须是包含
only php 的文件中的omitted 。
相信我,遵循这些标准可以为你节省很多时间。)
有时,当dev进程同时拥有win工作站和Linux系统(主机),并且在代码中,在相关行之前看不到任何输出时,可能是文件的格式设置和缺少unix lf(linefeed)。行结束。
为了快速修复这个问题,我们通常要做的是重命名文件,在Linux系统上创建一个新文件而不是重命名的文件,然后将内容复制到该文件中。很多时候,这就解决了这个问题,因为在Win中创建的一些文件一旦转移到宿主,就会导致这个问题。
对于我们通过ftp管理的站点,此修复是一个简单的修复,有时可以节省我们的新团队成员一些时间。
通常,当我们在回送或打印后发送头段时会出现此错误。如果在特定页面上出现此错误,则在调用
不可预测错误示例:
1 2 3 4 5 | <?php //a white-space before <?php also send for output and arise error session_start(); session_regenerate_id(); //your page content |
再举一个例子:
1 2 3 4 5 6 7 8 | <?php includes 'functions.php'; ?> <!-- This new line will also arise error --> <?php session_start(); session_regenerate_id(); //your page content |
结论:在调用