Buy

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():

86 lines src/AppBundle/Controller/Admin/GenusAdminController.php
... 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!

112 lines src/AppBundle/Entity/User.php
... 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:

398 lines vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
... 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:

53 lines app/Resources/views/base.html.twig
<!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':

9 lines app/Resources/views/main/homepage.html.twig
{% 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!

  • 2016-09-01 Victor Bocharsky

    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!

  • 2016-08-30 Javier Mendez

    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!