我在symfony 4.3中有一个奇怪的问题(也在4.2中进行了测试-行为相同)-我正在使用EventListener来处理请求-代码如下:
<?php
namespace App\EventListener;
use App\Entity\Company;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;
class ShopListener implements EventSubscriberInterface
{
/** @var EntityManagerInterface */
protected $em;
/** @var Environment */
protected $twig;
public function __construct(EntityManagerInterface $entityManager, Environment $twig)
{
$this->em=$entityManager;
$this->twig=$twig;
}
public function onKernelRequest(RequestEvent $event)
{
if($event->isMasterRequest()===false) {
return;
}
/** @var Request $request */
$request=$event->getRequest();
$subDomain=$request->attributes->get('domain');
if($subDomain===null) {
return;
}
$company=$this->em->getRepository(Company::class)->findOneBy([
'subDomain' => $subDomain,
]);
if($company instanceof Company && $company->shopIsOnline()) {
$request->attributes->set('company',$company);
return;
}
$event->setResponse(
new Response($this->twig->render('page/shop_not_found.html.twig'),404)
);
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => ['onKernelRequest',0],
];
}
}
注册该侦听器后,$request->getSession()
在我的控制器中始终为null
(工具栏还会注意到,没有注册会话)。注销时,会话在那里,但是侦听器中的逻辑被跳过。我尝试优先考虑以确保没有其他监听器会干扰。
看来,已经注册该事件会终止会话(即使onKernelRequest为空),这令人难以置信。
我想念什么?
答案 0 :(得分:2)
会话也是由DateTime
侦听器创建的,也是在Symfony\Component\FrameworkBundle\EventListener\SessionListener
事件(优先级为128)上创建的。
该事件具有特定的行为:如果侦听器设置了响应,则“该过程将直接跳至kernel.response事件”,以引用the documentation。我怀疑这可能会引起问题。
尝试将监听器的优先级设置为<0(我尝试了很多),请检查事件探查器“事件”部分(kernel.request
)的顺序。
答案 1 :(得分:2)
找到了解决方案-问题是在构造函数中注入了树枝环境-如果没有树枝,一切都会按预期进行。我猜想,在此阶段加载树枝环境会对会话有所帮助(例如过早加载)。 我将侦听器移至onKernelController并对其进行了修改:
<?php
namespace App\EventListener;
use App\Entity\Company;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;
class ShopListener implements EventSubscriberInterface
{
/** @var EntityManagerInterface */
protected $em;
/** @var Environment */
protected $twig;
public function __construct(EntityManagerInterface $entityManager, Environment $twig)
{
$this->em=$entityManager;
$this->twig=$twig;
}
public function onKernelController(ControllerEvent $controllerEvent)
{
if($controllerEvent->isMasterRequest()===false) {
return;
}
/** @var Request $request */
$request=$controllerEvent->getRequest();
$subDomain = $request->attributes->get('domain');
if($subDomain===null) {
return;
}
$company=$this->em->getRepository(Company::class)->findOneBy([
'subDomain' => $subDomain,
]);
if($company instanceof Company && $company->shopIsOnline()) {
$request->attributes->set('company',$company);
return;
}
$controllerEvent->setController(
function() {
return new Response($this->twig->render('page/shop_not_found.html.twig'),404);
}
);
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::CONTROLLER => ['onKernelController',128],
];
}
}