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.
There's really only 2 things you can do with security:
- Deny access
- 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:
<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.
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?