我在Symfony2控制器中有一个动作,它正在向客户端发送响应(如这里所示)。在函数发出响应之后,我有一个事件订阅者来监听onkernelTerminate事件,因为在响应发送到客户机之后,我将做一些繁重的工作。
对于正在做繁重工作的部分来说,一切似乎都正常工作,除了代码中有一行引用了一个利用Session的服务,该服务需要它来存储令牌并最终与外部API通信。
这个错误当然是:无法启动会话,因为头已经被发送了。
是否有办法开始一个会话,即使头已经发送?或者有什么更好的方法来处理这个问题?
我最终通过从传入请求中获取会话并将其存储到我的动作控制器中的本地变量来解决这个问题,然后确保会话被激活或启动:
use SymfonyComponentHttpFoundationRequest;
public function myFunctionAction(Request $request) {
$session = $request->getSession();
$session->start();
接下来,我立即将响应和头发送给客户端:
ob_start();
$response = new Response('Status: OK', 200);
echo $response; // send the response
header('Connection: close');
header('Content-Length: ' . ob_get_length());
ob_end_flush();
if (ob_get_level() > 0) {
ob_flush();
}
flush();
然后代码继续像往常一样做繁重的工作。然而,解决这个问题的关键是,确保使用Session的服务向引用它的其他服务提供保存或不保存服务内会话的选项。如果会话被保存,那么它将不再是活动的,它被关闭,一旦它被关闭,你不能再次启动它,因为头已经发送。然而,引用服务的客户端代码应该在会话结束时保存并关闭会话。
我最终没有监听内核。终止事件,因为在我的情况下不需要它。