Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Using a shortcut Base Controller Class

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

Using a shortcut Base Controller Class

Getting the security.context service requires too much typing. So let’s make some improvements so we can get things done faster.

Create a new class called Controller inside the EventBundle and make this class extend Symfony’s standard base controller. But watch out! Both classes are called Controller, so we need to alias Symfony’s class to BaseController:

// src/Yoda/EventBundle/Controller/Controller.php

namespace Yoda\EventBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller as BaseController;

class Controller extends BaseController
{
    // ...
}

Inside this class, create a function that returns the security context from the service container:

// src/Yoda/EventBundle/Controller/Controller.php
// ...

public function getSecurityContext()
{
    return $this->container->get('security.context');
}

Using the Custom Base Controller

Head back to EventController. Right now, this extends Symfony’s Controller, which means that we get access to all of its shortcuts. Remove the use statement for Symfony’s Controller and replace it with a use statement for our fancy Controller class:

// src/Yoda/EventBundle/Controller/EventController.php
// ...

use Yoda\EventBundle\Controller\Controller;

class EventController extends Controller
{
    // ...
}

Now we can access all of Symfony’s shortcut methods and the new getSecurityContext method we created. And actually, we don’t even need the use statement because this class lives in the same namespace as the new Controller class.

Ok! Let’s use the new getSecurityContext method to shorten things:

// src/Yoda/EventBundle/Controller/EventController.php
// ...

private function enforceUserSecurity($role = 'ROLE_USER')
{
    if (!$this->getSecurityContext()->isGranted($role)) {
        // in Symfony 2.5
        // throw $this->createAccessDeniedException('message!');
        throw new AccessDeniedException('Need '.$role);
    }
}

And even though we’re not really using its page, remove the use statement in DefaultController as well so that we’re using the new class:

// src/Yoda/EventBundle/Controller/DefaultController.php
// ...

// no use statement here anymore

class DefaultController extends Controller
{
// ...

Change the use statements in both RegisterController and SecurityController. In RegisterController, we can also take advantage of the new shortcut:

// src/Yoda/UserBundle/Controller/RegisterController.php
// ...

use Yoda\EventBundle\Controller\Controller;

class RegisterController extends Controller
{
    // ...

    private function authenticateUser(User $user)
    {
        $providerKey = 'secured_area'; // your firewall name
        $token = new UsernamePasswordToken($user, null, $providerKey, $user->getRoles());

        $this->getSecurityContext()->setToken($token);
    }
}
// src/Yoda/UserBundle/Controller/SecurityController.php
// ...

use Yoda\EventBundle\Controller\Controller;
// ...

class SecurityController extends Controller

These controllers do need to have a use statement, because they don’t live in the same namespace as the new Controller class.

Add More Methods to Controller!

Now that all of our controllers extend our Controller class, we can add whatever shortcut functions we want here. For example, if we needed to check for Event owner security in another controller, we could just move that function into Controller and make it public:

// src/Yoda/EventBundle/Controller/Controller.php
// ...

use Yoda\EventBundle\Entity\Event;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

class Controller extends BaseController
{
    // ...

    public function enforceOwnerSecurity(Event $event)
    {
        $user = $this->getUser();

        if ($user != $event->getOwner()) {
            // if you're using 2.5 or higher
            // throw $this->createAccessDeniedException('You are not the owner!!!');
            throw new AccessDeniedException('You are not the owner!!!');
        }
    }
}

Leave a comment!

2
Login or Register to join the conversation
Default user avatar
Default user avatar Junaid Farooq | posted 5 years ago

Hi,

If i put the enforceOwnerSecurity method in the parent controller class and then call it from the EventController class, it throws an exception but when i put it back in the latter, it works. I dont what i might be missing as i am fairly new to symfony. It maybe an error due to PHP 7 version which I am running with Symfony 2.4.

Reply

Hey Junaid,

It's difficult to guess the reasons, could you show us the error you see, and also print the code which causes this error? We'd be glad to help you.

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.3.3",
        "symfony/symfony": "~2.4", // v2.4.2
        "doctrine/orm": "~2.2,>=2.2.3", // v2.4.2
        "doctrine/doctrine-bundle": "~1.2", // v1.2.0
        "twig/extensions": "~1.0", // v1.0.1
        "symfony/assetic-bundle": "~2.3", // v2.3.0
        "symfony/swiftmailer-bundle": "~2.3", // v2.3.5
        "symfony/monolog-bundle": "~2.4", // v2.5.0
        "sensio/distribution-bundle": "~2.3", // v2.3.4
        "sensio/framework-extra-bundle": "~3.0", // v3.0.0
        "sensio/generator-bundle": "~2.3", // v2.3.4
        "incenteev/composer-parameter-handler": "~2.0", // v2.1.0
        "doctrine/doctrine-fixtures-bundle": "~2.2.0", // v2.2.0
        "ircmaxell/password-compat": "~1.0.3", // 1.0.3
        "phpunit/phpunit": "~4.1", // 4.1.0
        "stof/doctrine-extensions-bundle": "~1.1.0" // v1.1.0
    }
}
userVoice