我在Magento CE 1.6.1.0
中收到以下错误 Warning: session_start() [<a href='function.session-start'>function.session-start</a>]: Cannot send session cookie - headers already sent by (output started at /home/dev/env/var/www/user/dev/wdcastaging/lib/Zend/Controller/Response/Abstract.php:586) in /home/dev/env/var/www/user/dev/wdcastaging/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php on line 119
访问/api/soap/?wsdl
显然,在输出WSDL文件的全部内容后,正在尝试session_start()
,导致错误。
为什么magento在输出所有基准后尝试启动会话?我很高兴你问。因此,看起来controller_front_send_response_after
被Mage_Persistent迷住了,以便调用synchronizePersistentInfo()
,而session_start()
最终会触发persistent/options/enable
。
有趣的是,这不是始终正在发生,最初WSDL加载对我来说很好,最初我绞尽脑汁试着看看我们的安装到了什么样的定制。引起这种情况,但我所做的追踪似乎表明这完全发生在核心内部。
我们也经历了与Mage_Persistent的一点点(完全不相关)的陌生感,这让我更愿意在这一点上举起手来这样做。
我已经对SO进行了一些搜索,并且发现了一些与整个“已经发送的标题”相关的问题,但不是这个具体情况。
有什么想法吗?
哦,我现有的临时解决方法就是通过{{1}}配置数据禁用Mage_Persistent。我还做了一些挖掘,是否有可能观察一个事件,以便为WSDL控制器禁用此模块 (因为这似乎是唯一有问题的模块),但看起来该模块完全依赖于此配置标志来确定它的启用状态。
更新:已报告错误:http://www.magentocommerce.com/bug-tracking/issue?issue=13370
答案 0 :(得分:2)
我报告这是Magento团队的一个错误。 Magento API控制器都通过标准Magento动作控制器对象进行路由,所有这些对象都继承自Mage_Api_Controller_Action
类。这个类有一个preDispatch
方法
class Mage_Api_Controller_Action extends Mage_Core_Controller_Front_Action
{
public function preDispatch()
{
$this->getLayout()->setArea('adminhtml');
Mage::app()->setCurrentStore('admin');
$this->setFlag('', self::FLAG_NO_START_SESSION, 1); // Do not start standart session
parent::preDispatch();
return $this;
}
//...
}
其中包括设置一个标志以确保API方法无法启动正常的会话处理。
$this->setFlag('', self::FLAG_NO_START_SESSION, 1);
因此,听起来synchronizePersistentInf
中的代码假定存在会话对象,并且在使用它时会话被初始化,导致您看到的错误。通常,这不是问题,因为此时每个其他控制器都已初始化会话,但API控制器明确地将其关闭。
就修复问题而言,您最好的选择(可能是您从Magento支持获得的快速答案)将禁用默认配置设置的持久购物车功能,但随后为需要它的特定商店启用它。这将让购物车
自己想出一个解决方案将是一个未知的领域,我想不出一种方法可以做到这一点,不是非常hacky /不稳定。最直接的方法是在synchronizePersistentInf
上调用它的父方法的类重写,除非您检测到这是一个API请求。
答案 1 :(得分:0)
这个答案并不是要取代现有的答案。但是我想在这里删除一些代码以防有人遇到这个问题,并且注释并不真正允许代码格式化。
我使用简单的local
代码池覆盖Mage_Persistent_Model_Observer_Session
来退出/api/*
不要期望这个修复需要非常长寿或升级友好,b / c我希望他们在下一个版本中解决这个问题。
public function synchronizePersistentInfo(Varien_Event_Observer $observer)
{
...
if ($request->getRouteName() == 'api') {
return;
}
...
}