PHP 5.6:headers_sent间歇性地返回true,空文件名和第0行

时间:2017-03-16 07:17:22

标签: php http-headers php-extension php-5.6

我在我的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()和{{1}时,它只会(但不是总是)出现记录用户或重定向到登录页面。

我已阅读并重新阅读this answer一般"已发送的标题"错误,并且,尽我所能,我已经排除了这些可能的原因:

    在我致电setcookie()print 之前,
  1. HTML阻止或致电echosetcookie()
  2. 我的PHP标记之外的空格
  3. 材料清单
  4. header() php.ini设置
  5. auto_prepend_file流编码 - 已安装zlib,但gzip已关闭
  6. 重复zlib.output_compression php.ini设置
  7. 那个回答提到了

      

    如果没有错误来源具体化,它通常是PHP扩展或php.ini设置。

    所以,我现在正在查看我的扩展程序... extension=为我提供了一个包含这些条目的51长度数组:

    get_loaded_extensions

    我没有使用所有这些,所以我打算通过并删除未使用的,并希望其中一个导致问题。

    最糟糕的情况是,我会尝试碰撞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_bufferingob_start()来查看文件的开头和结尾。我不知道为什么当我目前的ob_end_flush()值为4096时,这会解决这个问题,而且我知道这种解决方法会带来自己的问题。

    我在这里缺少什么 - 我还需要检查其他可能的原因吗?我应该尝试不同的PHP版本,还是在没有扩展名的干净PHP安装上运行我的代码子集?

    编辑:添加了output_buffering调用和输出,以及有关能够通过启动新的Docker容器来始终如一地重现这一点的信息。删除了有关ob_get_contents()值的信息;更改此项仅发现了error_reporting弃用通知,修复了对此处描述的问题没有影响。

3 个答案:

答案 0 :(得分:1)

我已经看到由于过去的行结束格式而出现问题。您是否将文件从一个操作系统环境移动到另一个操作系统环境?

有时,隐藏的回车符(/ r)或其他特殊的空格字符会导致这种情况,但在文件中不可见。

答案 1 :(得分:1)

它可能是UTF8 BOM字符,或错误的换行符,不可打印的字符,错误的php关闭标记(我不使用它们,以防止终止问题)。即使没有这样的问题,即使你做了所有事情来阻止它,它也可以(并且将会)发生。问题可能出在FTP服务器,文本编辑器,错误的PHP配置,编码,错误的cgi配置上。为了防止所有这些,我使用空输出缓冲区,只需在第一个php文件中启动buffreing

的index.php:

if(version_compare(PHP_VERSION, '7.0.0') >= 0 || ob_get_level() < 1)
    ob_start();

HtmlResponce.php:

ob_end_clean();
echo $this->getRenderedContent();

FileResponce.php:

ob_end_clean();
readfile($this->content);

在php5和php7输出缓冲中几乎没有差别,也可以在php.ini中配置输出缓冲,并且在cgi和apache mod配置方面存在差异。你不要在“默认”配置上进行中继。要处理警告消息,请使用set_error_handler(),您也可以使用ob_end_clean()

删除它们

如果您开始查看symfony components的新项目,我会在CMS中使用很多项目。这是你用奇怪的PHP漏洞防止不眠之夜的机会。

答案 2 :(得分:1)

在删除了一些未使用的遗留代码(包括require_once对所有遗留代码的文件的调用后 - 此问题不再发生。它可能会在“断断续续的”#34;我最初观察到的条件,但我复制它的方法不再表现出这个问题。

我不知道为什么这似乎有帮助 - 删除的行完全在<php? ?>标记内,我检查了删除的文件,以查找标记,BOM和CRLF之外的空格。

我也不知道为什么这个问题是断断续续的;如果它与删除的代码或文件有关,那么它应该每次都发生。

感谢大家的评论和答案!