Magento调试:头信息已发送错误

13

我在系统日志文件中收到了以下错误信息:

 2011-01-12T14:16:52+00:00 DEBUG (7): HEADERS ALREADY SENT: 
 [0] C:\xampp\htdocs\www.mysite.com\app\code\core\Mage\Core\Controller\Response\Http.php:44
 [1] C:\xampp\htdocs\www.mysite.com\lib\Zend\Controller\Response\Abstract.php:727
 [2] C:\xampp\htdocs\www.mysite.com\app\code\core\Mage\Core\Controller\Response\Http.php:75
 [3] C:\xampp\htdocs\www.mysite.com\app\code\core\Mage\Core\Controller\Varien\Front.php:188
 [4] C:\xampp\htdocs\www.mysite.com\app\code\core\Mage\Core\Model\App.php:304
 [5] C:\xampp\htdocs\www.mysite.com\app\Mage.php:596
 [6] C:\xampp\htdocs\www.mysite.com\index.php:81

我知道“头已经发送”的意思,但我不知道是哪个文件导致了这个问题,而且追踪并没有给我任何信息。

有没有办法找出引起问题的文件?

谢谢!

11个回答

17

以下是较为麻烦的方法。

找到正在进行日志记录的文件位置。

C:\xampp\htdocs\www.mysite.com\app\code\core\Mage\Core\Controller\Response\Http.php 
Mage::log('HEADERS ALREADY SENT: '.mageDebugBacktrace(true, true, true));

为已经包含/引用的每个文件添加日志记录以获取副本

Mage::log(print_r(get_included_files(),true));

如果您记得将文件恢复到未被更改的状态,可以直接将此日志记录添加到核心文件中,或者您可以在临时副本中添加。

app/code/local/Mage/Core/Controller/Response/Http.php
只要你记得在使用完后删除它(或者使用git),就可以检查这个文件列表中通常的空格问题,然后检查其中可能会产生输出的任何函数(例如echo、print、readfile,可能还有其他函数)。

2
这正是我一直在寻找的,谢谢。我将逐个完成列表中的任务,并尽量在几年后回到这里报告。谢谢! - sulman
给Alan Storm,你能给我一个复制这个警告的例子吗? - Josua Marcel C
我尝试使用带有空格的闭合 PHP 标签 ?>,但没有成功。 - Josua Marcel C
1
下面的方法更好,应该被接受为答案。 - WonderLand

17

这里有一种更简单的方法。

查看文件中的canSendHeaders方法。

lib/Zend/Controller/Response/Abstract.php

为代码添加一些日志记录

public function canSendHeaders($throw = false)
{
    $ok = headers_sent($file, $line);
    // to get PHP's report on which file is sending a header.
    if ($ok !== false){
        Mage::log('File: ' . $file, null, 'exception.log', true);
        Mage::log('Line: ' . $line, null, 'exception.log', true);
    }

    if ($ok && $throw && $this->headersSentThrowsException) {
        #require_once 'Zend/Controller/Response/Exception.php';
        throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line);
    }

    return !$ok;
}

这只是记录了三个空行:2011-01-13T09:59:41+00:00 EMERG (0) - sulman
这不是 Mage::log 的正确语法。我会把这归咎于艾伦累了,这绝对不是他的典型行为。如果你在 Mage::log 中使用多个参数,第二个参数是错误级别,你需要第三个参数来指示日志文件。你真正想要的是 Mage::log("file: $file, line: $line") - Mageician
@BrianVPS 感谢提醒 - 我确实在脑海中搞错了 Mage::logvar_dump 的语法。已经更正了帖子。 - Alana Storm

11

该错误是从Mage_Core_Controller_Response_Http->sendHeaders()中抛出的。此函数调用了超类函数,实际上检查标头是否已经发送,即Zend_Controller_Response_Abstract->canSendHeaders()。

Zend_Controller_Response_Abstract类处理发送响应标头等事项,并跟踪上次发送标头的时间(以及来自哪个文件和行)。以下是该函数的样子,在lib\Zend\Controller\Response\Abstract.php中的第316行左右我们将进行更改:

public function canSendHeaders($throw = false) {
    $ok = headers_sent($file, $line);
    if ($ok && $throw && $this->headersSentThrowsException) {
        #require_once 'Zend/Controller/Response/Exception.php';
        throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line);
    }
    return !$ok;
}

收件人:

public function canSendHeaders($throw = false)
{
    $ok = headers_sent($file, $line);

    if ($ok) {
        Mage::log('Cannot send headers; headers already sent in ' . $file . ', line ' . $line, null, 'headers.log');
    }

    return !$ok;

    #if ($ok && $throw && $this->headersSentThrowsException) {
    #    #require_once 'Zend/Controller/Response/Exception.php';
    #    throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line);
    #}
    #return !$ok;
}

这将会把错误记录在 /var/log/header.log 文件中。


这是一个非常好的答案,正好提供了我需要追踪问题的详细信息。通过使用这个方法找到文件和@xyphoid的答案来理解原因,我成功地解决了它。我从不知道回显Ajax调用的响应是不好的。每天都会学到新东西 :) - Mageician

10

在Magento中最常见的情况是当您直接从控制器输出内容时。

与其这样做

echo $string; 

在控制器内部,执行此操作:

$this->getResponse()->setBody($string);

在我们的情况下,罪魁祸首是Mage_Adminhtml_Cms_WysiwygController::directiveAction,它输出了一张(几乎)直接的图像而没有使用setBody - jlilja
+1 不错!在输出时我写成了echo而不是$this->getResponse()->setBody($string);。希望下次我能记住 ;) - Damodar Bashyal

5

我也看到了这个问题。我认为这与所见即所得编辑器中的图像有关。在通过管理员(特别是CMS页面)时观察日志,您可能会看到它发生。这是无害的。


谢谢回复。实际上,这在所有前端页面视图中都发生了。我正在努力获得一个干净的system.log文件! - sulman
1
然后你应该开始查找输出之前的空格。 - Anton S
@clockworkgeek,我犯了同样的错误,但我想要复制这个错误。我已经通过在块、控制器、闭合标签和空格上直接使用echo来尝试,但仍未复制成功。如何复制这个警告?你知道怎么做吗? - Josua Marcel C
在CMS页面的所见即所得编辑器中去除HTML元素之间的空格(如@Anton所建议的)可以消除OP问题中的警告。注意:打开CMS页面的所见即所得编辑器似乎会插入空格。每次我打开CMS中的所见即所得编辑器(即使只是为了查看HTML),我都必须确保删除空格...这是Magento的另一个令人讨厌的特性。 - Vee

3
也许对某些人有帮助: 当我在CMS -> 页面中编辑页面时,启用Magento的所见即所得编辑器(WYSIWYG)时,我会收到类似的消息。如果页面包含CMS标记,例如:
{{store url='my-other-page'}}

在我点击“显示/隐藏编辑器”后,这条消息会出现在system.log中:

2013-04-06T11:10:38+00:00 DEBUG (7): HEADERS ALREADY SENT: <pre>[0] ...\app\code\core\Mage\Core\Controller\Response\Http.php:52
[1] ...\lib\Zend\Controller\Response\Abstract.php:766
[2] ...\app\code\core\Mage\Core\Controller\Response\Http.php:83
[3] ...\app\code\core\Mage\Core\Controller\Varien\Front.php:188
[4] ...\app\code\core\Mage\Core\Model\App.php:354
[5] ...\app\Mage.php:683
[6] ...\index.php:87
</pre>

0
当我以“hacky”的方式构建我的Ajax请求时,直接回显内容而不是通过布局发送它们,我收到了这个错误。一旦我通过布局发送它们,错误就消失了。请参见我的问题:从Magento管理扩展输出ajax数据的最佳方法 感谢@alan对我的问题的回答。

0

我在安装Magento时遇到了相同的问题。

在我的情况下,启用PHP中的output_buffering解决了这个问题。

在PHP 5.6的xampp中,默认情况下启用了output_buffering

在PHP 5.3的xampp中,默认情况下output_buffering是禁用的。


0

在进行Ajax调用时出现相同问题

当我从控制器直接调用模板时,会在进行Ajax调用时收到日志。

当我更改代码并在布局XML文件中创建块时,日志错误得到了修复。


0
我觉得这可能是OnePageCheckout扩展的问题。我在Magento中遇到了同样的错误,而且似乎这个错误并不那么常见。我也安装了OnePageCheckout。但是,当然,这可能只是巧合。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接