【问题标题】:Having an Event change a variable in the background让事件在后台更改变量
【发布时间】:2023-03-23 13:00:03
【问题描述】:

我看到了以下场景:

  • 针对 AD 运行身份验证
  • AD 服务器返回标识字符串“foo\bar”
  • 身份验证成功后,将触发事件“LOGIN_SUCCESS”,并将身份字符串和适配器作为参数

一旦触发此事件,就会附加多个触发器。

  1. 第一个侦听器检查数据库中是否已经存在具有匹配“身份 foo\bar”的用户行。如果没有,将创建一个用户行
  2. 每次登录时,另一个侦听器都会更新适配器提供的用户元数据
  3. 我想要第三个侦听器,将身份字符串“foo\bar”从数据库中的用户行更改为用户对象

目前我的AuthenticationService 看起来像这样:

if ($result->isValid()) {
    $currentIdentity = $result->getIdentity();

    $eventManager = new EventManager(__CLASS__);
    $eventResult = $eventManager->trigger(self::DUIT_USER_LOGIN_SUCCESSFUL, $this, [
        'identity' => $currentIdentity,
        'adapter' => $adapter
    ]);

    // This whole stuff sucks!
    if ($eventResult->last() instanceof EventInterface) {
        $identityObject = $eventResult->last()->getParam('identity');

        if ($identityObject instanceof User) {
            $this->getStorage()->write($identityObject);

            return $result;
        }
    }

    $this->getStorage()->write($result->getIdentity());
}

如您所见,我在这里做的事情并不真正属于AuthenticationServiceEvent 有没有办法修改给定的parameter(在本例中为identity),以便在后台更改参数的值?

我真的不想在AuthenticationService 中检查这个 eventResult。这个假设不应该存在,但我真的没有看到任何不同的做事方式。

//编辑

目前触发器正在后台执行此操作:

public function handleWorkflow(EventInterface $event)
{
    $identityString = $event->getParam('identity');

    $userObject = $this->userService->findByActiveDirectoryId($identityString);

    if ($userObject instanceof User) {
        return $event->setParam('identity', $userObject);
    }

    return $event->setParam('identity', $identityString);
}

【问题讨论】:

    标签: php zend-framework2


    【解决方案1】:

    正如在 IRC 上所讨论的,这种应用于事件数据的“转换”是微妙的,并且会让你反胃。

    如果您希望从事件数据中得到 string,则编写 IdentityFinder 或类似的代码并将其注入到您的 AuthenticationService 中:

    if ($result->isValid()) {
        $currentIdentity = $result->getIdentity();
    
        // we use some sort of locator to find the identity
        $identity = $this->identityLocator->find($currentIdentity);
    
        $this->getStorage()->write($identity);
    
        // triggering is still OK, but not to manipulate the data here.
        // it should also happen _AFTER_ successful authentication
        // I also assume you injected the EventManager here, instead of building it
        // result is also being ignored, it shouldn't contain data required to us
        $this->eventManager->trigger(
            self::DUIT_USER_LOGIN_SUCCESSFUL, 
            $this,
            [
                'identity' => $identity,
                'adapter' => $adapter
            ]
        );
    
    }
    

    如果结果仍然是传入的结果,那么只需实现一个虚拟的,就可以使这个查找器无操作:

    class NoopIdentityFinder implements IdentityFinderInterface
    {
        public function find($identity)
        {
            return $identity; // no real "find" going on
        }
    }
    

    通过这种方式,您仍然可以让事件侦听器“捕捉”发生的事情,从而明确且易于理解地编写逻辑代码。

    【讨论】:

      猜你喜欢
      • 2019-04-11
      • 1970-01-01
      • 2023-04-08
      • 2016-08-17
      • 1970-01-01
      • 2020-11-10
      • 2011-07-08
      • 2014-10-21
      • 1970-01-01
      相关资源
      最近更新 更多