Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Fetch me a User Object!

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

There's really only 2 things you can do with security:

  1. Deny access
  2. Find out who is logged in

To show that off, find newAction(). Let's update the flash message to include the email address of the current user.

Surround the string with sprintf and add a %s placeholder right in the middle. How can you find out who's logged in? Yep, it's $this->getUser(). And that returns - wait for it - our User object. Which allows us to use any methods on it, like getEmail():

... lines 1 - 15
class GenusAdminController extends Controller
{
... lines 18 - 34
public function newAction(Request $request)
{
... lines 37 - 40
if ($form->isSubmitted() && $form->isValid()) {
... lines 42 - 47
$this->addFlash(
'success',
sprintf('Genus created by you: %s!', $this->getUser()->getEmail())
);
... lines 52 - 53
}
... lines 55 - 58
}
... lines 60 - 85
}

But wait! Do we have a getEmail() method on User - because I didn't see auto-completion?! Check it out. Whoops - we don't!

My bad - head to the bottom and add it!

... lines 1 - 12
class User implements UserInterface
{
... lines 15 - 83
public function getEmail()
{
return $this->email;
}
... lines 88 - 110
}

Nice! Now go and create a sea monster. Fill out all the fields... and... eureka!

The Secret Behind getUser()

But you know I hate secrets: I want to know what that getUser() method really does. So hold Command and click to see that method.

The important piece is that the user comes from a service called security.token_storage:

... lines 1 - 38
abstract class Controller implements ContainerAwareInterface
{
... lines 41 - 317
/**
* Get a user from the Security Token Storage.
*
* @return mixed
*
* @throws \LogicException If SecurityBundle is not available
*
* @see TokenInterface::getUser()
*/
protected function getUser()
{
if (!$this->container->has('security.token_storage')) {
throw new \LogicException('The SecurityBundle is not registered in your application.');
}
if (null === $token = $this->container->get('security.token_storage')->getToken()) {
return;
}
if (!is_object($user = $token->getUser())) {
// e.g. anonymous authentication
return;
}
return $user;
}
... lines 344 - 396
}

So if you ever need the User object in a service, this is how to get it.

But, it takes a couple of steps: getToken() gives you a pretty unimportant object, except for the fact that you can call getUser() on it.

The Creepy anon.

But, there's a pitfall: if you are anonymous - so, not logged in - getUser() does not return null, as you might expect: it returns a string: anon.. I know - it's super weird. So, if you ever do fetch the user object directly via this service, check to make sure getUser() returns an object. If it doesn't, the user isn't logged in.

Getting the User in Twig

The one other place where you'll need to fetch the User is inside Twig. In fact, let's talk about security in general in Twig. Open up base.html.twig.

Earlier, we already showed how to check for a role in Twig: it's via the is_granted() function:

<!DOCTYPE html>
<html>
... lines 3 - 13
<body>
... lines 15 - 19
<header class="header">
... lines 21 - 22
<ul class="navi">
... line 24
{% if is_granted('ROLE_USER') %}
<li><a href="{{ path('security_logout') }}">Logout</a></li>
{% else %}
<li><a href="{{ path('security_login') }}">Login</a></li>
{% endif %}
</ul>
</header>
... lines 32 - 50
</body>
</html>

It's easy: it works exactly the same as in the controller.

So, how do we get the user object? To find out - open up the homepage template. If the User is logged in, let's welcome them by email.

Open the print tag and say app.user ? app.user.email : 'Aquanauts':

{% extends 'base.html.twig' %}
{% block body %}
<h1 class="page-header text-center">
Welcome
{{ app.user ? app.user.email : 'Aquanauts' }}!
</h1>
{% endblock %}

That app variable is the one global variable you get in Symfony. And one of its super-powers is to give you the current User object if there is one, or null if the user isn't logged in.

Head to the home page and... celebrate.

Leave a comment!

8
Login or Register to join the conversation
Default user avatar

hello, I encounter a problem in the method newAction, the part $ this-> getUser () -> getEmail (), the method getEmail () is not loaded. So I looked for why, I went to the file vendor / symfony / symfony / src / Symfony / Bundle / FrameworkBundle / Controller / Controller.php, but the latter is different, I did a composer update in git bash thinking that something was broken in symfony, but nothing works, I was also see a blank project where i install symfony and the file is identical, so I deduce that being at version 3.4 of symfony, the general configuration is different I do not know how to adapt this content for it to work. Could you help me please?

Reply

Hey teddy

Could you show me what does "$this->getUser()" returns to you? Or if you are getting any errors
I believe you are not getting the user object because you forgot to login in. but, well, let's check it out

Hive a nice day

Reply

What I like to do in my entities is to have a __toString() method. In this case it would return the email property.
You can then just call $this->getUser() in controller or app.user in twig.

If you add more properties to your User entity later, for example first name, last name etc. and want to show that instead of email, you dont have to edit all the files only toString method.

Reply

Hey edin

I like your approach, but I kind of see it like a personal preference, some guys may love it but some others may not like :)

Have a nice day!

Reply
Default user avatar

Hi, which plugin takes care of the app.user auto completion in twig (at 3:00 in the video)?

Reply

Hey Webber,

All that magic are from Symfony Plugin, see more info about it in our PhpStorm screencasts which is free: https://knpuniversity.com/s...

Cheers!

Reply
Default user avatar
Default user avatar Javier Mendez | posted 5 years ago

I added an extra property to the Users table, call it "University" and I would like to use such property to filter certain rows in the formType when creating a new entry to the Aquanaut table. So far I have been able to do it on my listAction function but I can not seem to be able to do it in the createAction function.

Thank you very much in advance!

Reply

Hey Javier,

If you want to filter entities in form type - you need a query_builder option, check Using a Custom Query for the Entities. With it you can make a custom query for entity list and return filtered list.

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.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.4", // 1.4.2
        "doctrine/doctrine-migrations-bundle": "^1.1" // 1.1.1
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0", // v3.1.3
        "nelmio/alice": "^2.1", // 2.1.4
        "doctrine/doctrine-fixtures-bundle": "^2.3" // 2.3.0
    }
}
userVoice