New in Symfony 3.2: User value resolver for controllers

Contributed by
Iltar van der Berg
in #18510.

In Symfony applications, controllers that make use of the base Controller class can get the object that represents the current user via the getUser() shortcut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
    public function indexAction()
    {
        $user = $this->getUser();
       // ...
    }
}

In the past, you could also get the current request object with the getRequest() shortcut, which was deprecated in Symfony 2.4 in favor of the Request type-hint:

1
2
3
4
5
6
7
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    public function indexAction(Request $request) { ... }
}

In Symfony 3.2, we've added a new user resolver that allows to get the current user in any controller via type-hinting and we deprecated the Controller::getUser() shortcut, which will be removed in Symfony 4.0:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\User\UserInterface;

class DefaultController extends Controller
{
    // when the user is mandatory (e.g. behind a firewall)
    public function fooAction(UserInterface $user) { ... }

    // when the user is optional (e.g. can be anonymous)
    public function barAction(UserInterface $user = null) { ... }
}

This feature uses the argument resolver extension mechanism that was introduced in Symfony 3.1. This mechanism allows to register your own value resolvers for controller arguments.

Comments

Cool :)
These mini update notifications posts are pretty cool.

Am I the only one seeing more changes in 3.1 -> 3.2 than in 2.8 -> 3.0 :)
@Angel you are right about the number of updates. The reason is that 3.0 contained zero new features (it only removed the features marked as deprecated in 2.8). We published just one "New in Symfony 3.0" article explaining this: http://symfony.com/blog/new-in-symfony-3-0
A great feature!
Why are you moving away from using base Controller class methods and pushing the injection of user, request, etc.?
Great addition!

Can `UserInterface` type be changed by a custom one?
@Sullivan no it cannot, because a typehint on your User entity would be ambiguous whether you want to get the User object corresponding to the current logged in user or the User object corresponding to a request attribute (param converters) so supporting child classes could have broken BC.
I am very happy to see this service-DI approach propagation over helper methods coupled to some base class.

This can be used in any service with ease.

Great job!
I find this feature to be cool, but I don't understand why it's so different than `$this->getUser();`... Plus, as you always have to implement your own user class, most of the time you won't be able to take benefits from proper IDE auto-complete, whereas you can override phpdoc for the user like this:
`
/** @var MyUserClass $user */
$user = $this->getUser();
`
Which is better for autocompletion.
I always use this docblock for my base controller class which extends the symfony base controller:

/**
* @method MyUserClass getUser()
*/

So I got autocompletion for the user methods in all my controller classes.
Assuming you have doc blocks on all your functions (which you should), you'd include this:

* @param UserInterface|MyUserClass $user

I agree that injecting the user object as a parameter, instead of calling $this->getUser(), feels cleaner and easier to test.
I prefer DI over inheritance, and not only is cleaner and easy to test but in the future with this params resolver there's no need for extend Base Controller
Can i use UserInterface and Request both on controller parameter in same time like

```
indexAction(UserInterface $user, Request $request) {}
```
The Link "argument resolver extension" leads to 404.

Everything that result in less methods in BaseController is a win.
Even with the different arguments, I still don't understand why it's not "good" to have something like $this->getUser();

:/

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.