Zend 2:如何在Module.php中获取闭包接受参数?

时间:2014-04-09 13:35:38

标签: php zend-framework2

编辑: 我应该解释这是一个必须使用\ authenticate到多个dbs的应用程序。我在自动加载配置中定义了所有数据库适配器,如下所示:

return array(
    'db' => array(
        //Default adapter retrieved with $sm->get('Zend\Db\Adapter\Adapter')
        'driver' => 'Pdo_Mysql',
        'dsn' => 'mysql:dbname=db1;host=myserver',
        'username' => $DBuser,
        'password' => $DBpass,
        //'driver_options' => array(
        //  PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
        //),
        'adapters' => array(
            'someDB' => array(
                'driver' => 'Pdo_Mysql',
                'dsn' => 'mysql:dbname=someDB;host=myserver',
                'username' => $DBuser,
                'password' => $DBpass,
            ),
            'someOtherDB' => array(
                'driver' => 'Pdo_Mysql',
                'dsn' => 'mysql:dbname=someOtherDB;host=myserver',
                'username' => $DBuser,
                'password' => $DBpass,
                'AppType' => 'myCustomProperty',
...

我有以下功能我试图转移到服务管理器:

public function getAuthService($db) {
    if (! $this->authService) {
        //All DBs using authentication must have a view_users view
        $dbAdapter = $this->getServiceLocator()->get($db);
        $authAdapter = new AuthAdapter($dbAdapter);
        $authAdapter
            ->setTableName('view_users')
            ->setIdentityColumn('username')
            ->setCredentialColumn('password')
            ->setCredentialTreatment('MD5(?)');
        ;
        $authService = new AuthenticationService();
        $authService->setAdapter($authAdapter);
        $this->authService = $authService;
    }
    return $this->authService;
}

我在服务管理器中有这个,但是如何修改它以便$ myParam在检索时可以传递?

public function getServiceConfig() {
    return array(
        'factories' => array(
            'AuthService' => function($sm) {
                $dbAdapter = $this->getServiceLocator()->get($myParam);
                $authAdapter = new AuthAdapter($dbAdapter);
                $authAdapter
                    ->setTableName('view_users')
                    ->setIdentityColumn('username')
                    ->setCredentialColumn('password')
                    ->setCredentialTreatment('MD5(?)');
                ;
                $authService = new AuthenticationService();
                $authService->setAdapter($authAdapter);

                return $authService;
            }
        )
    );
}

问题是我希望能够在从服务管理器检索它时将$ db param传递给工厂。

要明确这个问题并不是专门针对如何对多个数据库进行身份验证,因为这对我来说已经很好了,我只想将我的功能移到服务管理器中。

编辑:crisp回答了我的实际问题,但我发现我的真正问题是对如何使用Authentication类的误解。

长话短说,我有一个登录控制器,提示输入用户信用,然后检查用户对所有数据库的访问权限,并将此信息存储在Zend \ Authentication \ Storage \ Session中。然后从各种其他模块,只需调用Session上的read()并检索用户的授权信息。

1 个答案:

答案 0 :(得分:2)

您正在寻找的是AbstractFactory,它本身能够从服务名称确定要返回的服务。

来自抽象工厂的服务命名必须有一种模式,我建议您的用例使用AuthService\DbAdapterName模式。

考虑到这一点,你可以为它写一个工厂,比如这个......

<?php
namespace Application\Service;

use Zend\Authentication\AuthenticationService;
use Zend\Authentication\Adapter\DbTable as AuthAdapter;
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class AbstractAuthenticationServiceFactory implements AbstractFactoryInterface
{

    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) 
    {
        // the name must begin with authservice ($name is the lowercase canonical name)
        if (0 !== strpos($name, 'authservice')) {
            return false;
        }
        // remove authservice from the name, leaving just the db name
        $dbName = str_replace('authservice', '', $name);

        // we can create the service only if the service manager has the db
        return $serviceLocator->has($dbName);
    }

    public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) 
    {
        $dbName = str_replace('authservice', '', $name);

        $dbAdapter = $serviceLocator->get($dbName);
        $authAdapter = new AuthAdapter($dbAdapter);
        $authAdapter
            ->setTableName('view_users')
            ->setIdentityColumn('username')
            ->setCredentialColumn('password')
            ->setCredentialTreatment('MD5(?)');

        $authService = new AuthenticationService();
        $authService->setAdapter($authAdapter);

        return $authService;
    }
}

出厂后,您需要将其添加到service_manager键下的abstract_factories配置中...

// module.config.php
return array(
    'service_manager' => array(
         'abstract_factories' => array(
             'authservice' => 'Application\Service\AbstractAuthenticationServiceFactory',
         ),
     ),
);

然后,您可以使用servicelocator通过使用前面描述的模式获取AuthService个实例

$someDbAuth = $this->getServiceLocator()->get('AuthService\someDB');

$otherDbAuth = $this->getServiceLocator()->get('AuthService\someOtherDB');