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:
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!
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.
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.
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.
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
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.
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!
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!
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!
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!
// 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
}
}
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?