php - with - Symfony2: Inyectar usuario actual en Servicio
symfony 3.4 fosuserbundle (7)
Intento inyectar el usuario actualmente conectado a un servicio. Mi objetivo es ampliar algunas funcionalidades de ramas para que se muestren en función de las preferencias del usuario. En este ejemplo, quiero mostrar cualquier función de fecha usando la zona horaria específica del usuario.
No parece haber ninguna forma de inyectar al usuario actual en un servicio, lo cual me parece realmente extraño. Al inyectar el contexto de seguridad, no tiene un token incluso si el usuario está conectado
Estoy usando el paquete de usuario de FOS.
services:
...
twigdate.listener.request:
class: App/AppBundle/Services/TwigDateRequestListener
arguments: [@twig, @security.context]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
<?php
namespace App/AppBundle/Services;
use Symfony/Component/HttpKernel/HttpKernelInterface;
use Symfony/Component/HttpKernel/Event/GetResponseEvent;
class TwigDateRequestListener
{
protected $twig;
function __construct(/Twig_Environment $twig, SecurityContext $context) {
$this->twig = $twig;
//$this->user = $context->get...;
var_dump($context); die;
}
public function onKernelRequest(GetResponseEvent $event) {
// $this->twig->getExtension(''core'')->setDateFormat($user->getProfile()->getFormat());
// $this->twig->getExtension(''core'')->setTimeZone($user->getProfile()->getTimezone());
}
}
output:
object(Symfony/Component/Security/Core/SecurityContext)[325]
private ''token'' => null
private ''accessDecisionManager'' =>
object(Symfony/Component/Security/Core/Authorization/AccessDecisionManager)[150]
private ''voters'' =>
array
0 =>
object(Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter)[151]
...
1 =>
object(Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter)[153]
...
2 =>
object(Symfony/Component/Security/Acl/Voter/AclVoter)[155]
...
private ''strategy'' => string ''decideAffirmative'' (length=17)
private ''allowIfAllAbstainDecisions'' => boolean false
private ''allowIfEqualGrantedDeniedDecisions'' => boolean true
private ''authenticationManager'' =>
object(Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager)[324]
private ''providers'' =>
array
0 =>
object(Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider)[323]
...
1 =>
object(Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider)[149]
...
private ''eraseCredentials'' => boolean true
private ''alwaysAuthenticate'' => boolean false
¿Me estoy perdiendo de algo?
Creo que esta pregunta merece una respuesta actualizada desde 2.6.x + desde las nuevas mejoras del componente de seguridad.
use Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage;
class UserDateExtension extends /Twig_Extension
{
/**
* @var TokenStorage
*/
protected $tokenStorage;
/**
* @param /Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage $tokenStorage
*/
public function __construct(TokenStorage $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function getUser()
{
return $this->tokenStorage->getToken()->getUser();
}
public function getFilters()
{
return array(
''user_date'' => new /Twig_Filter_Method($this, "formatUserDate"),
);
}
public function formatUserDate($date, $format)
{
$user = $this->getUser();
// do stuff
}
}
Servicios.yml
twig.date_extension:
class: Acme/Twig/SpecialDateExtension
tags:
- { name: twig.extension }
arguments:
- "@security.token_storage"
Desde Symfony 2.6.
Necesitas usar @ security.token_storage
use Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface;
class UserDateExtension extends /Twig_Extension
{
/**
* @var TokenStorageInterface
*/
protected $tokenStorage;
/**
* @param $tokenStorage TokenStorage
*/
public function __construct(TokenStorage $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function getUser()
{
return $this->tokenStorage->getToken()->getUser();
}
public function getFilters()
{
return array(
''user_date'' => new /Twig_Filter_Method($this, "formatUserDate"),
);
}
public function formatUserDate($date, $format)
{
$user = $this->getUser();
// do stuff
}
}
Y Services.yml
twig.date_extension:
class: Acme/Twig/SpecialDateExtension
tags:
- { name: twig.extension }
arguments: ["@security.token_storage"]
referencia: symfony.com/blog/…
El usuario es un mal candidato para ser un servicio.
- Primero es un modelo, no un servicio
- En segundo lugar, existe la seguridad del servicio. Contexto desde el que puede obtener el usuario.
En una plantilla twig puedes usar app.user . Ver symfony doc global-template-variables . Si desea mostrar algo en función de los permisos del usuario, puede hacer {{is_granted (''ROLE_USER'')}}.
Puedes intentar inyectar @service_container
y hacer $this->container->get(''security.context'')->getToken()->getUser();
.
Recomendaría enlazar un evento diferente, si usa el evento kernel.controller, tendrá un token y no tendrá ningún problema. El token no está disponible en kernel.request
desde Symfony 2.3
Escribí una guía sobre cómo implementar 2.6+
usuario para Symfony 2.3+
2.6+
y 2.6+
en Twig en mi blog llamado Symfony 2.6+ zonas horarias de usuario .
Esto es muy superior al uso de una extensión Twig porque puede usar las funciones de formateo de fecha estándar en Twig, así como proporcionar una fecha UTC de backend separada, zonas horarias de fecha Twig predeterminadas y zonas horarias de fecha Twig definidas por el usuario.
Aquí está el extracto más importante:
src / AppBundle / EventListener / TwigSubscriber.php
<?php
namespace AppBundle/EventListener;
use AppBundle/Entity/User;
use Symfony/Component/EventDispatcher/EventSubscriberInterface;
use Symfony/Component/HttpKernel/Event/FilterControllerEvent;
use Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface;
class TwigSubscriber implements EventSubscriberInterface
{
protected $twig;
protected $tokenStorage;
function __construct(/Twig_Environment $twig, TokenStorageInterface $tokenStorage)
{
$this->twig = $twig;
$this->tokenStorage = $tokenStorage;
}
public static function getSubscribedEvents()
{
return [
''kernel.controller'' => ''onKernelController''
];
}
public function onKernelController(FilterControllerEvent $event)
{
$token = $this->tokenStorage->getToken();
if ($token !== null) {
$user = $token->getUser();
if ($user instanceof User) {
$timezone = $user->getTimezone();
if ($timezone !== null) {
$this->twig->getExtension(''core'')->setTimezone($timezone);
}
}
}
}
}
Ahora puedes usar twig como siempre y usa tus preferencias de usuario si están disponibles.
Yo usaría una extensión de ramita para eso:
class UserDateExtension extends /Twig_Extension
{
private $context;
public function __construct(SecurityContext $context)
{
$this->context = $context;
}
public function getUser()
{
return $this->context->getToken()->getUser();
}
public function getFilters()
{
return array(
''user_date'' => new /Twig_Filter_Method($this, "formatUserDate"),
);
}
public function formatUserDate($date, $format)
{
$user = $this->getUser();
// do stuff
}
Ahora en services.xml
<service id="user_date_twig_extension" class="%user_date_twig_extension.class%">
<tag name="twig.extension" />
<argument type="service" id="security.context" />
</service>
Luego en twig puedes hacer:
{{ date | user_date(''d/m/Y'') }}
services.yml
my_service:
class: ...
arguments:
- "@=service(''security.token_storage'').getToken().getUser()"
Service.php
protected $currentUser;
public function __construct($user)
{
$this->currentUser = $user;
}
http://symfony.com/doc/current/book/service_container.html#using-the-expression-language