我正在尝试将当前登录的用户注入服务。我的目标是扩展一些树枝功能,根据用户偏好输出它。在这个例子中,我想使用用户特定的时区输出任何日期函数。
似乎没有办法将当前用户注入服务,这对我来说似乎很奇怪。注入安全上下文时,即使用户已登录,它也没有令牌
我正在使用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
我错过了什么吗?
答案 0 :(得分:58)
我认为自从新安全组件改进以来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"
答案 1 :(得分:42)
我会使用枝条延伸:
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 :(得分:30)
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
答案 3 :(得分:4)
用户是服务的不良候选人。
在twig模板中,您可以使用 app.user 。请参阅symfony doc global-template-variables。 如果您想根据用户权限显示某些内容,可以执行{{is_granted('ROLE_USER')}}。
答案 4 :(得分:2)
来自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
答案 5 :(得分:1)
我建议绑定一个不同的事件,如果你使用kernel.controller事件,你将有一个令牌,没有问题。自kernel.request
Symfony 2.3
中无法使用该令牌
我在我的博客Symfony 2.6+ User Timezones上写了一篇关于如何在Twig中为Symfony 2.3+
和2.6+
实现用户时区的指南。
这远远优于使用Twig扩展,因为您可以使用Twig中的标准日期格式化功能,以及提供单独的后端UTC日期,默认的Twig日期时区和用户定义的Twig日期时区。
以下是最重要的摘录:
的src /的appbundle /事件监听/ 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);
}
}
}
}
}
现在您可以正常使用树枝,如果可用,它会使用您的用户偏好设置。
答案 6 :(得分:-9)
您可以尝试注入@service_container
并执行$this->container->get('security.context')->getToken()->getUser();
。