警告:无法修改头信息 - 头信息已经被发送(输出开始于 /some/file.php:12)位于 /some/file.php 的 第23行 错误消息中提到的行包含了
header()
和 setcookie()
的调用。这可能是什么原因?如何修复它?
header()
和 setcookie()
的调用。发送/修改HTTP头部的函数必须在任何输出之前调用。 摘要 ⇊ 否则调用将失败:
警告:无法修改头部信息 - 头部已经被发送(输出开始于 脚本:行号)
一些修改HTTP头部的函数包括:
输出可以是:
无意的:
<?php
之前或?>
之后的空格有意的:
print
、echo
和其他产生输出的函数<?php
代码之前的原始<html>
部分。要理解为什么必须在输出之前发送头部,需要查看一个典型的HTTP响应。PHP脚本主要生成HTML内容,但也向Web服务器传递一组HTTP/CGI头部:
HTTP/1.1 200 OK
Powered-By: PHP/5.3.7
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
<html><head><title>PHP page output page</title></head>
<body><h1>Content</h1> <p>Some more output follows...</p>
and <a href="/"> <img src=internal-icon-delayed> </a>
括号内的“output started at”注释更为重要。
它标识了先前输出的来源。在这个例子中,它是auth.php
和第52
行。那就是你需要寻找过早输出的地方。
典型原因:
"print
和echo
语句的有意输出将终止发送HTTP头部的机会。必须重新构建应用程序流程以避免这种情况。使用functions和模板方案。确保在写出消息之前调用header()
。
产生输出的函数包括:
print
、echo
、printf
、vprintf
trigger_error
、ob_flush
、ob_end_flush
、var_dump
、print_r
readfile
、passthru
、flush
、imagepng
、imagejpeg
等等和用户定义的函数。
.php
文件中未解析的HTML部分也是直接输出的。
必须在任何原始的<html>
块之前注意触发header()
调用的脚本条件。
<!DOCTYPE html>
<?php
// 头部已经太晚了。
使用模板方案将处理与输出逻辑分离。
如果警告指的是行内1
的输出,那么它主要是由于开头的空格、文本或HTML在<?php
标记之前。
<?php
# 在<?之前有一个空格/换行符 - 这已经封闭了它。
类似地,它也可能发生在附加的脚本或脚本段落中:
?>
<?php
PHP实际上会吞掉关闭标签后的单个换行符。但它不会弥补多个换行符或制表符或移入这些间隙的空格。
换行符和空格本身可能是一个问题。但还有一些“不可见”的字符序列可能会导致这个问题。最著名的是UTF-8 BOM(字节顺序标记),大多数文本编辑器不显示它。它是字节序列EF BB BF
,对于UTF-8编码的文档来说是可选的和多余的。然而,PHP必须将其视为原始输出。它可能显示为输出中的字符
(如果客户端将文档解释为Latin-1)或类似的“垃圾”。
特别是图形编辑器和基于Java的IDE对其存在毫无察觉。它们不可视化它(受Unicode标准的约束)。然而,大多数程序员和控制台编辑
error_reporting(E_ALL);
ini_set("display_errors", 1);
或者在所有其他方法都失败时,使用set_error_handler("var_dump");
说到重定向头部,你应该经常使用像这样的习惯用法来处理最终的代码路径:
exit(header("Location: /finished.html"));
最好是一个实用函数,当header()
失败时打印用户消息。
PHP的输出缓冲 是一种解决此问题的方法。它通常可靠运行,但不应替代正确的应用结构和将输出与控制逻辑分离。其真正目的是将分块传输最小化到Web服务器。
output_buffering=
设置仍然是有帮助的。可以在 php.ini 中进行配置,或者通过 .htaccess 或者甚至 .user.ini 在现代的 FPM/FastCGI 设置中进行配置。启用它将允许 PHP 缓冲输出而不是立即传递给 Web 服务器。因此,PHP 可以聚合 HTTP 头。
也可以通过调用 ob_start();
来启用它。然而,由于多种原因,这种方法不太可靠:
即使 <?php ob_start(); ?>
开始了第一个脚本,空白字符或 BOM 可能会在之前产生,导致其无效。
它可能会隐藏 HTML 输出的空白字符。但是一旦应用程序逻辑尝试发送二进制内容(例如生成的图像),缓冲的多余输出就成为一个问题。(需要使用 ob_clean()
进行进一步的解决。)
缓冲区大小有限,在使用默认值时很容易溢出。当发生这种情况时,这也不是罕见的,很难追踪到问题的所在。
如果您之前没有收到标题警告,则表示 output buffering php.ini 设置 已更改。当前/新服务器上可能尚未配置。
headers_sent()
进行检查您始终可以使用 headers_sent()
来探测是否仍然有可能发送标题。这对于有条件地打印信息或应用其他回退逻辑非常有用。
if (headers_sent()) {
die("Redirect failed. Please click on this link: <a href=...>");
}
else{
exit(header("Location: /user.php"));
}
<meta>
标签如果您的应用程序在结构上很难修复,那么一种简单(但有点不专业)的方法是注入一个HTML <meta>
标签来允许重定向。可以通过以下方式实现重定向:
<meta http-equiv="Location" content="http://example.com/">
或者稍作延迟:
<meta http-equiv="Refresh" content="2; url=../target.html">
这会导致在<head>
部分之后使用时产生非有效的HTML。大多数浏览器仍然接受它。
作为替代方案,可以使用JavaScript重定向进行页面重定向:
<script> location.replace("target.html"); </script>
虽然这通常比<meta>
的解决方法更符合HTML规范,但它依赖于支持JavaScript的客户端。
然而,当真正的HTTP header()调用失败时,这两种方法都可以作为可接受的备选方案。理想情况下,您应该始终将其与用户友好的消息和可点击的链接结合在一起,作为最后的手段。(例如,这就是http_redirect() PECL扩展所做的。)
setcookie()和session_start()都需要发送Set-Cookie: HTTP头。因此,相同的条件适用,并且会生成类似的错误消息以处理过早输出的情况。
(当然,它们还受到浏览器禁用cookie甚至代理问题的影响。会话功能显然还取决于可用的磁盘空间和其他php.ini设置等。)
?>
结束标签通常是一个好习惯,有助于最小化错误。这样文件末尾就不会出现不需要的空格,在稍后添加响应头时也更加方便。此外,如果您使用输出缓冲,并且不希望在包含文件生成的部分末尾添加不必要的空格,这也很实用。 - Nikita 웃$file = $line = null; headers_sent($file, $line); die("$file:$line");
将会告诉你确切是什么发送了头信息。不确定为什么,但有时似乎是这种情况。 - kmuenkel当你在发送HTTP头部(使用setcookie
或header
)之前发送任何内容时,就会触发该错误消息。导致在HTTP头部之前输出内容的常见原因包括:
无意中添加的空白符,通常出现在文件开头或结尾,例如:
<?php
// Note the space before "<?php"
?>
避免这种情况,只需省略结尾的 ?>
即可,因为它并不是必需的。
3F 3C
。你可以安全地删除文件开头的 BOM EF BB BF
。echo
、printf
、readfile
、passthru
、<?
标签之前的代码等。display_errors
php.ini 属性。PHP 不会因程序员的错误而崩溃,而是默默地修复错误并发出警告。虽然可以修改配置项 display_errors
或 error_reporting,但最好还是修复问题。empty
或 isset
来测试输入是否已设置的 $_POST['input']
),或者使用未定义的常量而不是字符串文字(例如 $_POST[input]
,注意缺少引号)。打开输出缓冲应该可以解决问题。在调用 ob_start
后,所有的输出都被缓存到内存中,直到你释放缓存,例如通过ob_end_flush
。
然而,虽然输出缓冲可以避免这些问题,但你应该真正确定为什么你的应用程序会在 HTTP 头之前输出 HTTP 内容。这就像接电话并讨论了你的一天和天气,然后再告诉那个打错号码的人他拨错了电话一样。
我以前遇到过这个错误,我相信所有的PHP程序员都至少遇到过一次。
可能的解决方案1
这个错误可能是由文件开头或结尾处的空格引起的。这些空格不应该存在。
例如)
<!-- THERE SHOULD BE NO BLANK SPACES HERE -->
<?php
echo "your code here";
?>
<!-- THERE SHOULD BE NO BLANK SPACES HERE -->
检查引起这个错误的文件相关的所有文件。
注意: 有时像gedit
(一个默认的Linux编辑器)这样的编辑器在保存文件时会添加一个空白行,这应该不会发生。 如果您使用Linux,可以使用VI编辑器删除页面末尾?>
后面的空格/行。
可能的解决方案2: 如果这不是您的情况,请使用ob_start进行输出缓冲:
<?php
ob_start();
// code
ob_end_flush();
?>
这将打开输出缓冲,页面头部将在页面被缓冲后创建。
ob_start()
只是隐藏问题,不要使用它来解决这个特定的问题。 - Ja͢ckob_start()
并不是用来“隐藏”问题的,它解决了这个问题。 - Tomas<?
前删除空格。 - Manish Shrivastava//header("Location:".ADMIN_URL."/index.php");
write
echo "<script>location.href = '".ADMIN_URL."/index.php?msg=$msg';</script>";
或者
?><script><?php echo "location.href = '".ADMIN_URL."/index.php?msg=$msg';";?></script><?php
通常是由于在启动会话之前脚本意外输出引起的。根据您当前的代码,您可以尝试使用输出缓冲来解决它。
尝试在脚本的顶部添加对 ob_start();
函数的调用,并在文档的末尾添加 ob_end_flush();
。
你需要
printf ("Hi %s,</br />", $name);
在设置 cookie 之前,这是不允许的。你不能在头部之前发送任何输出,甚至不能有一个空行。
第45-47行:
?>
<?php
那段代码输出了几个换行符,所以头部信息已经发送。只需删除那3行(毕竟这是一个完整的PHP块,不需要结束PHP解析然后重新开始),以及第60-62行类似的块,它就会正常工作。1) 在header(.......);
命令之前不应有任何输出(即echo..
或HTML代码)。
2) 删除<?php
和?>
标签之前和之后的任何空格(或换行符)。
3) 黄金法则! - 检查该php文件(以及如果您include
其他文件)是否具有UTF8无BOM编码(而不仅仅是UTF-8)。这在许多情况下是个问题(因为UTF8编码的文件在php文件开头有一个特殊字符,您的文本编辑器不会显示)!!!!!!!!!!
4) 在header(...);
之后必须使用exit;
5) 始终使用301或302引用:
header("location: http://example.com", true, 301 ); exit;
echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;
301
或 302
是重要的? - Jānis Elmeris这是因为这一行代码:
printf ("Hi %s,</br />", $name);
在发送头部信息之前,您不应该输出/打印任何内容。
<?php
标记之前添加一个空格(或不可见的特殊字符)可能会导致这个问题!尤其是当你在团队中工作,有人使用“弱”IDE或者用奇怪的文本编辑器搞乱了文件时,就会出现这种情况。我曾经见过这些事情发生过 ;)
ob_start
和ob_end_clean()
)。然后,您可以将cookie或会话设置为ob_get_contents()
,然后使用ob_end_clean()
来清除缓冲区。 - JacksafeRedirect
函数:https://github.com/heinkasner/PHP-Library/blob/master/extra.php - heinkasnerUTF-8
,而应该是UTF-8 (无 BOM)
。 - T.Todua