我怎样才能知道我的输出是从哪里开始的呢?


How can I find out where my output started?

我注意到在我的网站源代码的HTML上面有两行空行。它看起来像这样:

<!-- Two empty lines here, StackOverflow won't let me post empty lines -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html>

HTML是用PHP生成的。我怎样才能知道输出是从哪里开始的?

我尝试在<html>之后添加<?php header('...'); ?>,希望触发"无法修改标题"之类的错误。输出从……行开始。"

如果您想获得文件名和开始输出的行号,您可以调用headers_sent()函数和两个可选参数:

$sent = headers_sent($file, $line);

这两个变量$file$line将包含调用函数后您要查找的信息。您不需要等待错误消息(但是,如果您没有看到任何错误消息,并且希望查明来源,则可能需要刷新输出(在许多地方))。所以要确保输出缓冲是禁用的。

它可能不会触发错误,因为到目前为止您打印的内容太短,并且在header调用之前仍然被缓冲。

尝试输出更多数据,例如:

echo str_repeat('a', 10000);

然后尝试输出一些标题。然后,您应该看到预期的PHP错误(假设您的错误报告设置已适当调整)。

我在Drupal上遇到了同样的问题(很多文件),我尝试了上面的几个答案,但没有任何结果。

最后,我找到了find方法(参见:搜索带有BOM的UTF-8文件的优雅方法?),它指出了一个愚蠢的错误:模块文件开头的空格:

find . -type f -name '*.module' -print0 | xargs -0r awk '/^ / {print FILENAME}{nextfile}'
find . -type f -name '*.php' -print0 | xargs -0r awk '/^ / {print FILENAME}{nextfile}'
find . -type f -name '*.inc' -print0 | xargs -0r awk '/^ / {print FILENAME}{nextfile}'

要直接回答您的问题,任何echo、print语句或任何将结果直接返回给标准输出的函数都将导致开始输出。另外,如果在<?php标签开始前有任何HTML或文本或空行,这将导致输出开始。

您可以通过在条目文档的顶部<?php标记下方添加ob_start()来直接修复此问题。并在文档的末尾添加ob_end_flush()。它看起来像这样。

将此添加到文档的最上方:

<?php
    ob_start();
?>

将此添加到文档的最底部:

<?php
    echo ob_end_flush();
?>

这允许您保留当前代码,并在代码中需要它们的地方输出头文件,而不会出现错误。

通过在PHP中放置这些行来显示错误:

error_reporting(E_ALL);
ini_set('display_errors','on');

这会触发报头错误!

它可能在PHP文件的末尾;您应该考虑删除结束PHP标记(?>)来消除这个问题。

我刚刚遇到了隐藏bom的类似问题,但这也适用于空白行和其他虚假字符,所以我想在这里添加我的发现。

添加假标题(");在代码中调用是找到输出开始位置的最佳方法,但是……最有可能的是,PHP配置默认启用了output_buffering。看看这个

通过在脚本开头添加以下内容:

if (ob_get_level()) ob_end_clean();

将关闭输出缓冲,并使header()调用报错,并说明输出开始的位置。

如果您的代码中第一个<?php上面有任何空行(假设您在文件的'顶部'有它)