php - 让事件在后台更改变量

标签 php zend-framework2

我有以下场景:

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

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

  1. 第一个监听器检查数据库中具有匹配“identity 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);
}

最佳答案

正如在 IRC 上讨论的那样,这种应用于事件数据的“转换”是微妙的,会反咬你一口。

如果您希望从您的事件数据中得到一个 string,那么请编写一个 IdentityFinder 或类似的代码并将其注入(inject)您的 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
        ]
    );

}

如果结果仍然是传入的结果,那么通过实现一个虚拟的让这个 finder 无操作:

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

通过这种方式,您仍然允许事件监听器“捕获”发生的事情,从而明确且易于理解地编写逻辑。

关于php - 让事件在后台更改变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21878001/

相关文章:

php - 在 WooCommerce 上为当前产品创建订单的按钮

php - 如何使用 Composer 将 FirePHP 添加到 Zend Framework 2

php - ZF-2 获取模块Controller文件中的模块名称 Action 方法

zend-framework2 - 如何在 ZF2 中将变量全局传递给 layout.phtml?

php - Zend 框架 - 错误不会登录

PHP hash_hmac() 操作系统差异

php - 如何将日文英文字符转换为普通英文字符?

javascript - 世界杯预测系统排名

php - sql delete with select 条件

zend-framework2 - 在 Zend Framework 2 中扩展 Zend\View\Helper\Url