ZF3 多数据库适配器
ZF3 multiple database adapters
在 ZF2 中可以像这样在 module.config.php
:
中配置多个适配器
'db' => array(
'adapters'=>array(
'db1' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'zf2',
'password' => 'zf2test',
),
'db2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf1;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'zf1',
'password' => 'zf1test',
),
)
),
在控制器工厂中,我可以通过 ServiceManager 获取它们:
class AlbumControllerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$albumTable = $serviceLocator->getServiceLocator()->get('Album\Model\AlbumTable');
$db1Adapter = $serviceLocator->getServiceLocator()->get('db1');
$db2Adapter = $serviceLocator->getServiceLocator()->get('db2');
return new AlbumController($albumTable, $db1Adapter, $db2Adapter);
}
}
现在我正尝试在 Zend Framework 3 中做同样的事情 - 但这个嵌套数组配置不起作用:
Fatal error: Uncaught exception 'Zend\Db\Adapter\Exception\InvalidArgumentException' with message 'createDriver expects a "driver" key to be present inside the parameters' in /var/www/USER/teckert/zf3/vendor/zendframework/zend-db/src/Adapter/Adapter.php:262
我认为在 ZF 2 中,当 dbAdapter 试图创建驱动程序时,adapters
键已经被处理了——但这在 ZF 3 中没有发生。
热烈欢迎任何提示...
zend-db with the adapters section 的手册对我来说不够清晰
编辑
根据 this doc,我已将以下代码片段添加到全局配置文件中:
'service_manager' => [
'abstract_factories' => [
\Zend\Db\Adapter\AdapterAbstractServiceFactory::class,
],
],
在我的 AlbumTableFactory
中尝试使用 $container->get('db1')
获取 dbAdapter 时出现此错误:
Unable to resolve service "db1 to a factory; are you certain you provided it during configuration?
确保您已将 Zend\Db\Adapter\AdapterAbstractServiceFactory
添加到 ServiceManager 配置的 abstract_factories
数组中。
这个抽象工厂负责实例化各个数据库适配器。另外,检查您的 Album\Model\AlbumTable
工厂是否检索了名称正确的数据库适配器。
好的,我终于解决了问题。
如@Pieter 所述,我的 config.php
中需要以下数组内容:
'service_manager' => [
'abstract_factories' => [
\Zend\Db\Adapter\AdapterAbstractServiceFactory::class,
],
],
此外,我不得不更改我的 类 和相关工厂相互交谈的流程。
AlbumControllerFactory
被调用并获取依赖的 AlbumTable
服务 ($container->get(AlbumTable::class);
),然后触发 AlbumTableFactory
AlbumTableFactory
然后正在为 AlbumTable
和 $tableGateway = $container->get(AlbumTableGateway::class);
准备构造函数注入
- 现在我将
AlbumTableFactory
和 AlbumTableGatewayFactory
的逻辑合并为一个 AbstractFactoryInterface
(我完全删除了 AlbumTableGatewayFactory)
// AlbumTableFactory implements AbstractFactoryInterface
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$dbAdapter = $container->get('db1');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Album());
$tableGateway = new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
return new AlbumTable($tableGateway);
}
在 ZF2 中可以像这样在 module.config.php
:
'db' => array(
'adapters'=>array(
'db1' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'zf2',
'password' => 'zf2test',
),
'db2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf1;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'zf1',
'password' => 'zf1test',
),
)
),
在控制器工厂中,我可以通过 ServiceManager 获取它们:
class AlbumControllerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$albumTable = $serviceLocator->getServiceLocator()->get('Album\Model\AlbumTable');
$db1Adapter = $serviceLocator->getServiceLocator()->get('db1');
$db2Adapter = $serviceLocator->getServiceLocator()->get('db2');
return new AlbumController($albumTable, $db1Adapter, $db2Adapter);
}
}
现在我正尝试在 Zend Framework 3 中做同样的事情 - 但这个嵌套数组配置不起作用:
Fatal error: Uncaught exception 'Zend\Db\Adapter\Exception\InvalidArgumentException' with message 'createDriver expects a "driver" key to be present inside the parameters' in /var/www/USER/teckert/zf3/vendor/zendframework/zend-db/src/Adapter/Adapter.php:262
我认为在 ZF 2 中,当 dbAdapter 试图创建驱动程序时,adapters
键已经被处理了——但这在 ZF 3 中没有发生。
热烈欢迎任何提示...
zend-db with the adapters section 的手册对我来说不够清晰
编辑
根据 this doc,我已将以下代码片段添加到全局配置文件中:
'service_manager' => [
'abstract_factories' => [
\Zend\Db\Adapter\AdapterAbstractServiceFactory::class,
],
],
在我的 AlbumTableFactory
中尝试使用 $container->get('db1')
获取 dbAdapter 时出现此错误:
Unable to resolve service "db1 to a factory; are you certain you provided it during configuration?
确保您已将 Zend\Db\Adapter\AdapterAbstractServiceFactory
添加到 ServiceManager 配置的 abstract_factories
数组中。
这个抽象工厂负责实例化各个数据库适配器。另外,检查您的 Album\Model\AlbumTable
工厂是否检索了名称正确的数据库适配器。
好的,我终于解决了问题。
如@Pieter 所述,我的 config.php
中需要以下数组内容:
'service_manager' => [
'abstract_factories' => [
\Zend\Db\Adapter\AdapterAbstractServiceFactory::class,
],
],
此外,我不得不更改我的 类 和相关工厂相互交谈的流程。
AlbumControllerFactory
被调用并获取依赖的AlbumTable
服务 ($container->get(AlbumTable::class);
),然后触发AlbumTableFactory
AlbumTableFactory
然后正在为AlbumTable
和$tableGateway = $container->get(AlbumTableGateway::class);
准备构造函数注入
- 现在我将
AlbumTableFactory
和AlbumTableGatewayFactory
的逻辑合并为一个AbstractFactoryInterface
(我完全删除了 AlbumTableGatewayFactory)
// AlbumTableFactory implements AbstractFactoryInterface
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$dbAdapter = $container->get('db1');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Album());
$tableGateway = new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
return new AlbumTable($tableGateway);
}