在我的应用程序(ZF2 / ORM)中我有3个实体(具有单表继承)
用户
所有者扩展用户
代理扩展用户
我想使用3个实体进行一次身份验证(登录) doctrine.authenticationservice.orm_default
module.config.php
//other doctrine config
'authentication' => array(
'orm_default' => array(
'object_manager' => 'Doctrine\ORM\EntityManager',
'identity_class' => 'Application\Entity\User',
'identity_property' => 'email',
'credential_property' => 'password',
'credential_callable' => function(User $user, $passwordGiven) {
return $user->getPassword() == md5($passwordGiven);
},
),
),
和登录过程
// LoginController.php
// ..data validation
$this->authService = $this->getServiceLocator()->get('doctrine.authenticationservice.orm_default');
$AuthAdapter = $this->authService->getAdapter();
$AuthAdapter->setIdentity($this->request->getPost('email'));
$AuthAdapter->setCredential(md5($this->request->getPost('password')));
$result = $this->authService->authenticate();
if($result->isValid()){
$identity = $result->getIdentity();
//continue
}
如何在不关心对象类型的情况下完成此过程, 当我尝试使用代理的电子邮件登录时,我收到此错误
捕获致命错误:传递给Application \ Module :: {closure}()的参数1必须是User的实例,Application \ Entity \ Owner的实例
答案 0 :(得分:2)
您提到的错误是由于类型提示:
function(User $user) {
这让我相信你的配置文件中缺少名称空间声明;在这种情况下,您可以添加它或使用FQCN。
function(\Application\Entity\User $user) {
尽管如此,我认为这不是问题。您只能使用doctrine身份验证定义一个“identity_class”(适配器将使用该身份验证从实体管理器加载实体)。如果您有多个实体类,则无法使用一个适配器测试每个实体类。
但是,配置实际上只是创建一个新的身份验证适配器,特别是DoctrineModule\Authentication\Adapter\ObjectRepository
。一种解决方案是创建多个ObjectRepository
适配器,每个适配器具有不同实体的正确配置,然后在authenticate()
上调用Zend\Authentication\AuthenticationService
时循环遍历每个适配器。
例如:
public function methodUsedToAutheticate($username, $password)
{
// Assume we have an array of configured adapters in an array
foreach($adapters as $adapter) {
$adapter->setIdentity($username);
$adapter->setCredential($password);
// Authenticate using the new adapter
$result = $authService->authenticate($adapter);
if ($result->isValid()) {
// auth success
break;
}
}
return $result; // auth failed
}
如前所述,doctrine配置不允许使用多个适配器,因此您需要手动创建它们并删除当前配置。
另一个例子
public function getServiceConfig()
{
return [
'factories' => [
'MyServiceThatDoesTheAuthetication' => function($sm) {
$service = new MyServiceThatDoesTheAuthetication();
// Assume some kind of api to add multiple adapters
$service->addAuthAdapter($sm->get('AuthAdapterUser'));
$service->addAuthAdapter($sm->get('AuthAdapterOwner'));
$service->addAuthAdapter($sm->get('AuthAdapterAgent'));
return $service;
},
'AuthAdapterAgent' => function($sm) {
return new DoctrineModule\Authentication\Adapter\ObjectRepository(array(
'object_manager' => $sm->get('ObjectManager'),
'identity_class' => 'Application\Entity\Agent',
'identity_property' => 'email',
'credential_property' => 'password'
));
},
'AuthAdapterOwner' => function($sm) {
return new DoctrineModule\Authentication\Adapter\ObjectRepository(array(
'object_manager' => $sm->get('ObjectManager'),
'identity_class' => 'Application\Entity\Owner',
'identity_property' => 'email',
'credential_property' => 'password'
));
},
// etc...
],
];
}
希望这能为您提供一些必要的想法。
最后,如果您考虑其他模块,ZfcUser
already has a 'chainable adapter'实际执行上述操作(但使用事件管理器),那么即使您不使用它也可能值得一看。