Symfony - 在 onKernelRequest 中使用 twig 终止会话

Symfony - using twig in onKernelRequest kills session

我在 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 为空),这很难相信。 我错过了什么?

会话由 Symfony\Component\FrameworkBundle\EventListener\SessionListener 侦听器在 kernel.request 事件上创建(优先级为 128)。
此事件具有特定行为:如果侦听器设置响应,"the process skips directly to the kernel.response event" 引用 the documentation。我怀疑它可能会导致问题。
尝试将您的监听器的优先级设置为 < 0(我让您尝试了很多次),并请检查探查器 "Events" 部分 (/_profiler/latest?panel=events).

的顺序

找到解决方案 - 问题是在构造函数中注入 twig-environment - 没有树枝一切都按预期工作。我想,在此阶段加载 twig-environment 会对会话产生影响(比如过早加载)。 我将侦听器移至 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],
        ];
    }
}