【发布时间】:2017-08-07 05:49:03
【问题描述】:
我在我的 PHP 脚本(PHP 5.6、Apache 2.2)中间歇性地遇到这个问题:
警告:无法修改标头信息 - 标头已在第 55 行的 /path/to/index.php 中发送
这个警告没有我在其他问题中看到的“发送者”部分,所以我在有问题的 header() 和 setcookie() 调用之前添加了这段代码:
if (headers_sent($filename, $linenum)){
echo("Output buffer: #" . ob_get_contents() . "#");
echo "Headers already sent in $filename on line $linenum: ";
print_r(headers_list());
}
这是我在问题发生时得到的输出:
Output buffer: ##
Headers already sent in on line 0:
Array (
[0] => X-Powered-By: PHP/5.6.23
[1] => Content-type: text/html; charset=UTF-8
)
(旁注:我在 php.ini 中将 output_buffering 设置为 4096 字节,所以这两个标头中的 63 个字符不应该被缓冲并等待更多,而不是过早发送吗?)
这个问题在我第一次启动包含网络服务器的 Docker 容器时出现。之后,它仅(但不是总是)在我一段时间内(可能是一两个小时)第一次访问我的网站时发生,当我调用header() 和setcookie() 进行登录时用户进入或重定向到登录页面。
我已经反复阅读this answer 到一般的“标头已发送”错误,并且尽我所能排除了这些可能的原因:
- 在我调用
setcookie()或header()之前,HTML 会阻止或调用print、echo等 - PHP 标记外的空白
- 物料清单
-
auto_prepend_filephp.ini 设置 -
gzip流编码 - zlib 已安装,但zlib.output_compression已关闭 - 复制
extension=php.ini 设置
那个答案提到了
如果没有具体化错误源,通常是 PHP 扩展或 php.ini 设置。
所以,我现在正在查看我的扩展...get_loaded_extensions 给了我一个 51 长度的数组,其中包含这些条目:
Core, date, ereg, libxml, openssl,
pcre, zlib, filter, hash, Reflection,
SPL, session, standard, apache2handler, bz2,
calendar, ctype, curl, dom, exif,
fileinfo, ftp, gd, gettext, iconv,
mysqlnd, PDO, Phar, posix, shmop,
SimpleXML, snmp, soap, sockets, sqlite3,
sysvmsg, sysvsem, sysvshm, tokenizer, xml,
xmlwriter, xsl, mysql, mysqli, pdo_mysql,
pdo_sqlite, wddx, xmlreader, json, zip, mhash
我没有使用所有这些,所以我计划检查并删除未使用的,并希望其中一个导致问题。
在最坏的情况下,我会尝试将我的 output_buffering 值或使用 ob_start() 和 ob_end_flush() 到我的文件的开头和结尾。我不知道为什么当我当前的 output_buffering 值 4096 没有解决它时,这会解决它,而且我知道这种解决方法有其自身的问题。
我在这里遗漏了什么——我需要检查其他可能的原因吗?我应该尝试不同的 PHP 版本,还是在没有扩展的干净 PHP 安装上运行我的代码子集?
编辑:添加了ob_get_contents() 调用和输出,以及有关能够通过启动新的 Docker 容器来持续重现此内容的信息。删除了关于我的 error_reporting 值的信息;更改此设置仅发现了 always_populate_raw_post_data 弃用通知,修复了对此处描述的问题没有影响。
【问题讨论】:
-
请提供您设置的完整 PHP 文件代码并检查其中的标题。我想是
index.php?如果包含,请提供整个包含链源,包括索引文件。 -
您是否在入口点脚本的开头调用
ob_start()?您的问题尚不清楚,但没有ob_get_contents()将无法工作。另外,请尝试使用var_dump(ob_get_contents())。我认为这比简单地回显值要好,因为它会说出字符串的长度。 -
您如何确定修复
always_populate_raw_post_data问题并没有解决问题?这当然是一个原因。另一方面,查看成功加载的扩展也无济于事;相反的情况可能会触发错误 - failure 加载扩展。如果它显示第 0 行,则可以确定它与代码无关,而是在 PHP 本身初始化时触发了某些东西。 -
@GustavoStraube 啊,我假设
ob_get_contents()可以与我在php.ini 中的output_buffering设置一起使用。也许我从根本上误解了输出缓冲。 -
@ChristosLytras 这些文件是封闭源代码,但如果有必要,我会看看发布它们。
标签: php http-headers php-extension php-5.6