MouLingtao
MouLingtao

Reputation: 40

Symfony: Set response in base controller

<?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(){
    }
}

I need to directly returns a Response on 'containerInitialized' function, not need to call Action's function!

My current practices is throw 'SetResponseException', and listen 'onKernelException' event, when Exception is instance of 'SetResponseException', just replace Response content! But I think a little farfetched!

Upvotes: 0

Views: 501

Answers (1)

Federkun
Federkun

Reputation: 36964

What you really want is use an event listener.

<?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',
        );
    }
}

then add this to you configuration

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

now you can just do this:

namespace AppBundle\Controller;

// ...

abstract class BaseController extends Controller
{
    // other stuff
}

namespace AppBundle\Controller;

// ...

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

for each controller that will extends BaseController, the BaseControllerListener::onKernelController method will be executed.

Upvotes: 2

Related Questions