php Symfony2:在服务中注入当前用户

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9990625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 08:02:18  来源:igfitidea点击:

Symfony2: Inject current user in Service

phpdependency-injectionsymfonyfosuserbundle

提问by n0xie

I am trying to inject the currently logged in user into a service. My goal is to extend some twig functionality to output it based on user preferences. In this example I want to output any date function using the user specific Timezone.

我正在尝试将当前登录的用户注入服务。我的目标是扩展一些树枝功能以根据用户偏好输出它。在这个例子中,我想使用用户特定的时区输出任何日期函数。

There doesn't seem to be any way to inject the current user into a service, which seems really odd to me. When injecting the security context, it doesn't have a token even if the user is logged in

似乎没有任何方法可以将当前用户注入到服务中,这对我来说似乎很奇怪。注入安全上下文时,即使用户已登录也没有令牌

I am using FOS user bundle.

我正在使用 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

Am I missing something?

我错过了什么吗?

回答by Michael Villeneuve

I think that this question deserves an updated answer since 2.6.x+ since the new security component improvements.

我认为自从新的安全组件改进以来,这个问题值得更新自 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

服务.yml

twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments:
        - "@security.token_storage"

回答by miguel_ibero

I would use a twig extension for that:

我会为此使用树枝扩展名:

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
    }

Now in services.xml

现在在 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>

Then in twig you could do:

然后在树枝中你可以这样做:

{{ date | user_date('d/m/Y') }}

回答by Alex

services.yml

服务.yml

my_service:
    class: ...
    arguments:
        - "@=service('security.token_storage').getToken().getUser()"

Service.php

服务.php

protected $currentUser;

public function __construct($user)
{
    $this->currentUser = $user;
}

http://symfony.com/doc/current/book/service_container.html#using-the-expression-language

http://symfony.com/doc/current/book/service_container.html#using-the-expression-language

回答by Maksim Kotlyar

The user is a bad candidate to be a service.

用户不适合成为服务。

  • First it is a model not a service
  • Second there is service security.contextwhere you can get user from.
  • 首先它是一个模型而不是一个服务
  • 其次是服务security.context,您可以从中获取用户。

In a twig template you can use app.user. See symfony doc global-template-variables. If you want to show something based on user permissions you can do {{ is_granted('ROLE_USER') }}.

在树枝模板中,您可以使用app.user。参见 symfony 文档global-template-variables。如果您想根据用户权限显示某些内容,您可以执行 {{ is_granted('ROLE_USER') }}。

回答by Chrysweel

From Symfony 2.6.

来自 Symfony 2.6。

You need use @security.token_storage

您需要使用@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
}

}

}

And Services.yml

和服务.yml

twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments: ["@security.token_storage"]

reference: http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements

参考:http: //symfony.com/blog/new-in-symfony-2-6-security-component-improvements

回答by Finlay Beaton

I would recommend binding a different event, if you use the kernel.controller event, you will have a token and have no problem. The token is not available in kernel.requestsince Symfony 2.3

我建议绑定一个不同的事件,如果你使用 kernel.controller 事件,你将有一个令牌并且没有问题。令牌不可用,kernel.request因为Symfony 2.3

I wrote a guide on how to implement User Timezones for Symfony 2.3+and 2.6+in Twig on my blog called Symfony 2.6+ User Timezones.

我在我的博客Symfony 2.6+ User Timezones上写了一篇关于如何为TwigSymfony 2.3+2.6+在 Twig 中实现用户时区的指南。

This is vastly superior to using a Twig Extension because you can use the standard date formatting functions in Twig, as well as provide separate backend UTC date, default Twig date timezones and User defined Twig date timezones.

这比使用 Twig 扩展要好得多,因为您可以使用 Twig 中的标准日期格式功能,并提供单独的后端 UTC 日期、默认 Twig 日期时区和用户定义的 Twig 日期时区。

Here is the most important excerpt:

这是最重要的摘录:

src/AppBundle/EventListener/TwigSubscriber.php

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);
                }
            }
        }
    }
}

Now you can use twig as normal and it uses your User preferences if available.

现在您可以像往常一样使用 twig,它会使用您的用户首选项(如果可用)。

回答by Mun Mun Das

You can try injecting @service_containerand do $this->container->get('security.context')->getToken()->getUser();.

您可以尝试注入@service_container并执行$this->container->get('security.context')->getToken()->getUser();.