Symfony:在基本控制器中设置响应

时间:2016-08-04 05:17:39

标签: php symfony

<?php
abstract class BaseController extends Controller {
    public function setContainer(ContainerInterface $container) {
        parent::setContainer($container);
        $this->containerInitialized();
    }
    protected function containerInitialized() {
        if($this->getUser()->getNickName()===null){
            // I need to directly returns a Response
            return new Response('...');
        }
    }
}

class UserHomeController extends BaseController{
    public function indexAction(){
    }
}

我需要直接在&#39; containerInitialized&#39;上返回一个回复。功能,不需要调用Action的功能!

我目前的做法是抛出&#39; SetResponseException&#39;,并听取onKernelException&#39; event,当Exception是&#39; SetResponseException&#39;的实例时,只需替换Response内容!但我觉得有点牵强!

1 个答案:

答案 0 :(得分:2)

您真正想要的是使用事件监听器。

<?php

namespace AppBundle\EventListener;

use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\HttpFoundation\Response;
use AppBundle\Controller\BaseController;

class BaseControllerListener implements EventSubscriberInterface
{
    private $tokenStorage;

    public function __construct(TokenStorageInterface $token_storage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function onKernelController(FilterControllerEvent $event)
    {
        if (!$this->isBaseController($event->getController())) {
            return;
        }

        if ($this->tokenStorage->getToken()->getUser()->getNickName() === null) {
            $event->setResponse(new Response('...'));
        }
    }

    protected function isBaseController($controller)
    {
        if (!is_array($controller)) {
            return;
        }

        return $controller[0] instanceof BaseController;
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::CONTROLLER => 'onKernelController',
        );
    }
}

然后将此添加到您的配置

services:
    app.base_controller_subscriber:
        class: AppBundle\EventListener\BaseControllerListener
        arguments:
            - "@security.token_storage"
        tags:
            - { name: kernel.event_subscriber }

现在你可以这样做:

namespace AppBundle\Controller;

// ...

abstract class BaseController extends Controller
{
    // other stuff
}

namespace AppBundle\Controller;

// ...

class UserHomeController extends BaseController
{
    public function indexAction()
    {
    }
}

对于将扩展BaseController的每个控制器,将执行BaseControllerListener :: onKernelController方法。