Symfony2: вводить текущего пользователя в службу
Я пытаюсь ввести текущего пользователя в службу. Моя цель состоит в том, чтобы расширить некоторые функциональные возможности, чтобы выводить их на основе пользовательских настроек. В этом примере я хочу вывести любую функцию даты, используя пользовательский часовой пояс.
Кажется, что нет никакого способа вставить текущего пользователя в сервис, который кажется мне очень странным. При вводе контекста безопасности он не имеет токена, даже если пользователь зарегистрирован в
Я использую пользовательский комплект 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
Я что-то пропустил?
Ответы
Ответ 1
Я бы использовал расширение для twig:
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
}
Теперь в 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>
Затем в твинге вы можете сделать:
{{ date | user_date('d/m/Y') }}
Ответ 2
Я думаю, что этот вопрос заслуживает обновленного ответа с 2.6.x +, так как новые улучшения компонента безопасности.
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
}
}
Services.yml
twig.date_extension:
class: Acme\Twig\SpecialDateExtension
tags:
- { name: twig.extension }
arguments:
- "@security.token_storage"
Ответ 3
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
Ответ 4
Пользователь является плохим кандидатом на роль службы.
- Сначала это модель, а не сервис
- Во-вторых, существует служба security.context, из которой вы можете получить доступ.
В шаблоне ветки вы можете использовать app.user. См. Symfony doc global-template-variables.
Если вы хотите показать что-то на основе прав пользователя, вы можете сделать {{is_granted ('ROLE_USER')}}.
Ответ 5
Из Symfony 2.6.
Вам нужно использовать @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
}
}
И Services.yml
twig.date_extension:
class: Acme\Twig\SpecialDateExtension
tags:
- { name: twig.extension }
arguments: ["@security.token_storage"]
ссылка: http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements
Ответ 6
Я бы рекомендовал привязать другое событие, если вы используете событие kernel.controller, у вас будет токен и не будет проблем. Токен не доступен в kernel.request
, поскольку Symfony 2.3
Я написал руководство по использованию пользовательских часовых поясов для Symfony 2.3+
и 2.6+
в Twig в моем блоге под названием Symfony 2.6+ User Timezones.
Это значительно превосходит использование расширения Twig, поскольку вы можете использовать стандартные функции форматирования даты в Twig, а также предоставлять отдельную временную дату UTC, временные метки даты Twig по умолчанию и пользовательские временные интервалы даты Twig.
Вот наиболее важный отрывок:
ЦСИ/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);
}
}
}
}
}
Теперь вы можете использовать веточку как обычно, и она использует ваши настройки пользователя, если они доступны.
Ответ 7
Вы можете попробовать ввести @service_container
и сделать $this->container->get('security.context')->getToken()->getUser();
.