Symfony在SwitchUserListener中注入EntityManager

时间:2018-11-07 11:31:21

标签: php symfony symfony-2.3

我的问题是关于如何在已经有9个参数的SwitchUserListener中注入实体管理器。

我有一个自定义的交换机用户流,我需要在会话中设置与_switch_user参数(?_switch_user = user1&external_client_id = 1)一起传递的ExternalClient。首先,必须先从数据库中获取ExternalClient。

在我添加的parameters.yml中

security.authentication.switchuser_listener.class: App\Bundle\Listener\SwitchUserListener

对于App\Bundle\Listener\SwitchUserListener的内容,我使用了Symfony SwitchUserListener Symfony\Component\Security\Http\Firewall\SwitchUserListener.php

一切正常,当我从侦听器中的请求变量中获取external_client_id参数时,它将被填充。但是我似乎无法访问实体管理器。

我尝试过的事情:

  1. services.yml中添加装饰器

    app.decorating_switch_user:
      class:     App\Bundle\Listener\SwitchUserListener
      decorates: security.authentication.switchuser_listener
      arguments: ['@app.decorating_switch_user.inner', '@doctrine.orm.entity_manager']
      public:    false
    
  2. 覆盖services.yml

    中的父项依赖项
    security.authentication.switchuser_listener:
      abstract:  true
    
    test:
      class: "%security.authentication.switchuser_listener.class%"
      parent: security.authentication.switchuser_listener
      public: false
      # appends the '@doctrine.orm.entity_manager' argument to the parent
      # argument list
      arguments: ['@doctrine.orm.entity_manager']
    
  3. 改为收听SwitchUserEvent

     app.switch_user_listener:
       class: App\Bundle\Listener\SwitchUserListener
       tags:
          - { name: kernel.event_listener, event: security.switch_user, method: onSwitchUser }
    

    在这里,我将“ App \ Bundle \ Listener \ SwitchUserListener”的内容替换为:

    class SwitchUserListener
    {
        public function onSwitchUser(SwitchUserEvent $event)
        {
            $request = $event->getRequest();
            echo "<pre>";
            dump($externalClientId = $request->get('external_client_id'));
            echo "</pre>";
            exit;
        }
    }
    

    通过这种尝试,我也获得了external_client_id,但是我不知道如何注入实体管理器。即使我这样做,也无法获得发起_switch_user请求的原始用户。 SwitchUserEvent仅有权使用getTargetUser()方法。

结论:

如果有人对这个主题有经验并愿意分享,那就太好了。理想情况下,我会将实体管理器服务添加到__construct函数的前9个参数中。我正在扩大课程,就像Matt在这里一样:Symfony2: Making impersonating a user more friendly

1 个答案:

答案 0 :(得分:1)

您可以按以下说明覆盖服务。在symfony版本之间更改时,您可能需要查找/更改服务参数的具体顺序。诸如$providerKey之类的某些参数可以留空,因为它们会由symfony自动更改/注入。

为了节省一些时间,如果您使用setter注入,则不需要重写构造函数。

看看Symfony的默认SwitchUserListener(切换到应用程序中使用的标记/版本)将有助于实现新的handle方法。

# app/config/services.yml
services:
  # [..]
  security.authentication.switchuser_listener:
    class: 'Your\Namespace\SwitchUserListener'
    public: false
    abstract: true
    arguments: 
      - '@security.context'
      - ~
      - '@security.user_checker' 
      - ~
      - '@security.access.decision_manager' 
      - '@?logger' 
      - '_switch_user' 
      - ~
      - '@?event_dispatcher' 
      - ~
    calls:
      - [ 'setEntityManager', [ '@doctrine.orm.entity_manager' ]]
    tags:
      - { name: monolog.logger, channel: security }

现在您的SwitchUserListener可能看起来像这样:

namespace Your\Namespace;

use Symfony\Component\Security\Http\Firewall\SwitchUserListener as DefaultListener;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

class SwitchUserListener extends DefaultListener
{
    /** @var EntityManagerInterface */
    protected $em;

    public function setEntityManager(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    /**
     * Handles the switch to another user.
     *
     * @throws \LogicException if switching to a user failed
     */
     public function handle(GetResponseEvent $event)
     {
          // Do your custom switching logic here
     }
}

别忘了清除缓存!