現在ログインしているユーザーをサービスに挿入しようとしています。私の目標は、いくつかのtwig機能を拡張して、ユーザー設定に基づいて出力することです。この例では、ユーザー固有のタイムゾーンを使用して日付関数を出力します。
現在のユーザーをサービスに投入する方法はないようです。セキュリティコンテキストを注入するとき、ユーザーがログインしていてもトークンを持たない
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
何か不足していますか?
そのために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>
次に、twigでできること:
{{ date | user_date('d/m/Y') }}
この質問は、新しいセキュリティコンポーネントの改善以来、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"
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
ユーザーはサービスの候補として不適切です。
twigテンプレートで使用できますapp.user。symfony doc global-template-variables 。ユーザー権限に基づいて何かを表示したい場合は、{{is_granted( 'ROLE_USER')}}を実行できます。
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
Kernel.controllerイベントを使用する場合、トークンがあり、問題はありません。別のイベントをバインドすることをお勧めします。 kernel.request
以降、トークンはSymfony 2.3
で使用できません
Symfony 2.3+
と2.6+
のユーザータイムゾーンを実装する方法に関するガイドをTwigと呼ばれる私のブログで Symfony 2.6+ User Timezones と書きました。
これは、Twigで標準の日付フォーマット関数を使用でき、別個のバックエンドUTC日付を提供できるため、Twig拡張機能を使用するよりもはるかに優れています。デフォルトTwig日付のタイムゾーンとユーザー定義Twig日付のタイムゾーン。
最も重要な抜粋は次のとおりです。
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);
}
}
}
}
}
これでtwigを通常どおり使用でき、利用可能な場合はユーザー設定が使用されます。