简体   繁体   English

Symfony 3 - 无法将 token_storage 传递给订阅者

[英]Symfony 3 - Can't pass token_storage to from subscriber

I want to get current logged user in form event but for some reason I can't get it to work.我想在表单事件中获取当前登录的用户,但由于某种原因我无法让它工作。

I used services to inject token_storage and create constructor method to fetch token storage instance but I got error right at constructor:我使用服务注入 token_storage 并创建构造函数方法来获取令牌存储实例,但在构造函数中出现错误:

Type error: Argument 1 passed to AdminBundle\Form\EventListener\CompanyFieldSubscriber::__construct() must implement interface Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface, none given

I am not sure what is the problem and how to fix it.我不确定是什么问题以及如何解决它。 Does someone knows where is the problem?有人知道问题出在哪里吗?

EDIT 1:编辑 1:

I think that I found out where is the problem but I can't find "good" solution.我想我发现了问题出在哪里,但我找不到“好的”解决方案。 I call this event in form type in this way:我以这种方式在表单类型中调用此事件:

->addEventSubscriber(new CompanyFieldSubscriber());

Problem is that I am not using 'service/dependency injection' to create event and I am sending nothing to constructor.问题是我没有使用“服务/依赖注入”来创建事件,并且我没有向构造函数发送任何内容。 That's why I have this error (not 100% sure to be hones).这就是为什么我有这个错误(不是 100% 肯定是磨练的)。

Since I have around 20-30 forms and new forms will come in time I need to create service for each form that requires user (or token_storage) instance and as a argument call token_storage or this event subscriber as a argument of service.由于我有大约 20-30 个表单,并且新表单将及时出现,我需要为每个需要用户(或 token_storage)实例的表单创建服务,并将其作为参数调用 token_storage 或此事件订阅者作为服务参数。

I know that it will work if I create each form as a service and pass required data as arguments but is there way to process this "automatically" without creating new service for every form that needs to have some user data interaction in form events?我知道如果我将每个表单创建为服务并将所需的数据作为参数传递,它会起作用,但是有没有办法“自动”处理这个而不为每个需要在表单事件中进行一些用户数据交互的表单创建新服务?

EDIT 2:编辑2:

As suggested I tried to change event subscriber constructor but I got same error with different class name.正如建议的那样,我尝试更改事件订阅者构造函数,但是我遇到了不同类名的相同错误。

New code:新代码:

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

public function __construct(TokenStorage $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

New error:新错误:

Type error: Argument 1 passed to AdminBundle\Form\EventListener\CompanyFieldSubscriber::__construct() must be an instance of Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage, none given

This is code I am using:这是我正在使用的代码:

Services:服务:

admin.form.event_listener.company:
    class:  AdminBundle\Form\EventListener\CompanyFieldSubscriber
    arguments: ['@security.token_storage']
    tags:
        - { name: form.event_listener }

Event Listener:事件监听器:

namespace AdminBundle\Form\EventListener;

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class CompanyFieldSubscriber implements EventSubscriberInterface
{
    private $tokenStorage;

    private $user;

    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
        $this->user = $this->tokenStorage->getToken()->getUser();
    }

    public static function getSubscribedEvents()
    {
        return [
            FormEvents::PRE_SET_DATA => 'preSetData',
            FormEvents::PRE_SUBMIT => 'preSubmitData',

        ];
    }

    public function preSetData(FormEvent $event)
    {

        $form = $event->getForm();

        if (in_array("ROLE_SUPER_ADMIN", $this->user->getRoles())) {
            $form->add('company', EntityType::class, [
                'class' => 'AppBundle:Company',
                'choice_label' => 'name'
            ]);
        }
    }

    public function preSubmitData(FormEvent $event)
    {

        $form = $event->getForm();
        $bus = $form->getData();


        if (!in_array("ROLE_SUPER_ADMIN", $this->user->getRoles())) {
            $bus->setCompany($this->user->getCompany());

        }
    }
}

You call subscriber in wrong way when you use: 您在使用时以错误的方式呼叫订户:

new CompanyFieldSubscriber()

You do not pass TokenStorageInterface to subscriber constructor. 您不将TokenStorageInterface传递给订阅者构造函数。 Call it as a service, if it is in controller then: 将该服务称为服务,如果它在控制器中,则:

->addEventSubscriber($this->get('admin.form.event_listener.company'));

if it is in form than pass from controller to form 如果是形式,则从控制器传递到形式

$this->get('admin.form.event_listener.company') 

as option and then use it in form 作为选项,然后以表格形式使用

for Symfony >= 4对于 Symfony >= 4

use Symfony\Component\Security\Core\Security;

class ExampleService
{
    private $security;

    public function __construct(Security $security)
    {
        $this->security = $security;
    }

    public function someMethod()
    {
        $user = $this->security->getUser();
    }
}

See doc: https://symfony.com/doc/current/security.html#fetching-the-user-from-a-service见文档: https : //symfony.com/doc/current/security.html#fetching-the-user-from-a-service

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM