我有以下场景:
- 针对 AD 运行身份验证
- AD 服务器返回一个身份字符串“foo\bar”
- 身份验证成功后,将触发事件“LOGIN_SUCCESS”,并将身份字符串和适配器作为参数
一旦触发此事件,就会附加多个触发器。
- 第一个监听器检查数据库中具有匹配“identity foo\bar”的用户行是否已经存在。如果没有,将创建一个用户行
- 在每次登录时,另一个监听器将更新适配器提供的用户元数据
- 我想要第三个监听器,将身份字符串“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());
}
如您所见,我在这里做的事情实际上不属于 AuthenticationService
。 Event
是否可以修改给定的 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/