Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Symfony2:将当前用户注入服务_Php_Dependency Injection_Symfony_Fosuserbundle - Fatal编程技术网

Php Symfony2:将当前用户注入服务

Php Symfony2:将当前用户注入服务,php,dependency-injection,symfony,fosuserbundle,Php,Dependency Injection,Symfony,Fosuserbundle,我正在尝试将当前登录的用户注入服务。我的目标是扩展一些细枝功能,根据用户偏好输出它。在本例中,我希望使用用户特定的时区输出任何日期函数 似乎没有任何方法将当前用户注入到服务中,这对我来说真的很奇怪。注入安全上下文时,即使用户登录,它也没有令牌 我正在使用FOS用户包 services: ... twigdate.listener.request: class: App\AppBundle\Services\TwigDateRequestListener

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

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

我正在使用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
服务:
...
twigdate.listener.request:
类:App\AppBundle\Services\TwigDataRequestListener
参数:[@twig,@security.context]
标签:
-{name:kernel.event_侦听器,事件:kernel.request,方法:onKernelRequest}

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

我会用一根树枝来做:

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>

用户不适合作为服务

  • 首先,它是一个模型而不是一个服务
  • 第二个是service security.context,您可以从中获取用户
在细枝模板中,您可以使用app.user。见symfony文件。
如果您想基于用户权限显示某些内容,您可以执行{{is_grated('ROLE_user')}}

我认为,自从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
    }
}
服务.yml

twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments:
        - "@security.token_storage"
my_service:
    class: ...
    arguments:
        - "@=service('security.token_storage').getToken().getUser()"
twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments: ["@security.token_storage"]

我建议绑定一个不同的事件,如果您使用kernel.controller事件,您将拥有一个令牌并且没有问题。由于
Symfony 2.3

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

这远远优于使用Twig扩展,因为您可以使用Twig中的标准日期格式功能,还可以提供单独的后端UTC日期、默认Twig日期时区和用户定义的Twig日期时区

以下是最重要的摘录:

src/AppBundle/EventListener/TwigSubscriber.php

services.yml

twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments:
        - "@security.token_storage"
my_service:
    class: ...
    arguments:
        - "@=service('security.token_storage').getToken().getUser()"
twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments: ["@security.token_storage"]
Service.php

protected $currentUser;

public function __construct($user)
{
    $this->currentUser = $user;
}
来自Symfony 2.6的

您需要使用@security.token\u存储

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

和服务.yml

twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments:
        - "@security.token_storage"
my_service:
    class: ...
    arguments:
        - "@=service('security.token_storage').getToken().getUser()"
twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments: ["@security.token_storage"]

参考资料:

在大多数情况下,注射整个容器是个坏主意。相反,您应该显式地注入您需要的每个服务。细枝扩展是此规则的例外之一。@elnur,对不起,我错了。助手服务
FacebookExtension
似乎使用have标记。这可能与扩展冲突。你说得对注入
@service\u容器是个坏主意。你可以只注入
安全性。上下文
。您不需要注入所有服务容器。@skonsoft,是的,您是对的。在回答这个问题时,我对服务定位器反模式感到困惑。但我仍然没有更新答案,因为我想留下我自己当时愚蠢的痕迹:)谢谢,这工作做得很好。我仍然不明白为什么我的第一个示例没有返回user对象,但是我让它工作了,我认为细枝扩展实际上是一种更干净的方法。感谢您对
kernel.request
事件的快速回复。通过身份验证或从会话读取令牌来设置上下文令牌是在所有
内核。请求
侦听器被调度之后完成的。如果您侦听了
kernel.response
事件,那么您将获得所需的令牌。也很抱歉误读了你的问题。今天对我来说是糟糕的一天:)。这是有道理的。谢谢你的解释。你每天都会学到一些东西。SecurityContext(security.context)从2.6开始就不推荐使用。使用security.token_storage代替标题除了@nutrija的评论外,请参阅:这是2016年symfony 2.6的最佳答案,它是否在安全防火墙之外工作?我的意思是,它是返回“null”还是抛出异常,因为getToken()返回null并且->getUser()不能应用于null对象?对于Symfony 3.2很好。我相信这是在没有用户的情况下抛出错误。