-
-
Save tentacode/ef4d19b390a599be74a6 to your computer and use it in GitHub Desktop.
<?php | |
namespace Tentacode\App\Security; | |
trait ConnectedUser | |
{ | |
/** | |
* @Inject | |
* @var Symfony\Component\Security\Core\SecurityContext | |
*/ | |
private $securityContext; | |
public function getConnectedUser() | |
{ | |
$token = $this->securityContext->getToken(); | |
if (!$token) { | |
throw new \RuntimeException('No user is connected.'); | |
} | |
return $token->getUser(); | |
} | |
} |
<?php | |
return [ | |
'Symfony\Component\Security\Core\SecurityContext' => DI\link('security.context'), | |
// ... | |
]; |
<?php | |
namespace Tentacode\App\Controller\Person; | |
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | |
use Tentacode\App\Security\ConnectedUser; | |
use Tentacode\App\Templating\Templating; | |
use Tentacode\Domain\Person\PersonRepository; | |
use Tentacode\Domain\User; | |
class ProfileController | |
{ | |
use ConnectedUser; | |
protected $templating; | |
protected $personRepository; | |
public function __construct(Templating $templating, PersonRepository $personRepository) | |
{ | |
$this->templating = $templating; | |
$this->personRepository = $personRepository; | |
} | |
public function myProfileAction() | |
{ | |
$user = $this->getConnectedUser(); | |
return $this->templating->render('TentacodeAppBundle:Person:profile.html.twig', [ | |
'user' => $user | |
]); | |
} | |
} |
CONS : it's not testable, you cannot have a property with the same name in top class.
PROS : it looks nice and it's a bit quicker to access in top class.
It might be better to use a service instead and inject it
Also, an alternative to traits (beberlei: http://www.whitewashing.de/2013/06/27/extending_symfony2__controller_utilities.html): having a ControllerUtils
class that can be injected and that exposes methods like shown above.
Though I'd rather use your solution because shoving everything into a generic ControllerUtils
doesn't look good for separation of concerns and all.
Yeah well, and any class with Utils
in its name is just "some big class I'm going to put everything in it"
But yeah, the solution is probably the best, but I won't use a single Utils class, more like several services that do their own stuff.
Why not move the other two dependencies to traits to follow this to its conclusion. Here traits are just making up for the fact that it's overly verbose to have a property and a constructor arg and and assignment for every damn dependency. The bad is that it does cause your constructor to lie about dependencies so this can only be safely built in a PHP-DI environment. So it would be somewhat better to move ALL dependencies to PHP-DI-injected and make the constructor private (or have it throw an exception).
Cleaner would be to move getConnectedUser to a direct dependency and inject that instead of security context. Then you really just have a clean set of dependencies each in a trait for less verbosity.
yeah, that's what I'll be doing in practice, @Inject on properties, and utility services
This is just a thing that crossed my mind, it's not supposed to be a good practice or something. Main goal is to have simple utility methods directly accessible by any class, without having any injections. It's also better than having a huge
BaseController
class for example.