Symfony-在onKernelRequest中使用树枝

时间:2019-06-02 11:35:15

标签: php symfony symfony4

我在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为空),这令人难以置信。 我想念什么?

2 个答案:

答案 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],
        ];
    }
}