我使用doctrine2和ZF2,我的一些库使用Zend \ Db \ Adapter \ Adapter,其他库使用doctrine2。现在,他们连接到数据库两次。是否可以在doctrine和标准ZF2 db adapter中使用一个db连接?
答案 0 :(得分:10)
DoctrineORM
模块接受PDO
资源或服务名称,其中实例可以位于服务管理器中,而不是通常的连接参数。
第一步是创建一个服务工厂,从Zend\Db\Adapter\Adapter
服务
<?php
namespace Application\Db\Service;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
class PdoResourceFactory implements FactoryInterface
{
/**
* @param ServiceLocatorInterface $serviceLocator
* @return \PDO resource
*/
public function createService(ServiceLocatorInterface $services)
{
$dbAdapter = $services->get('Zend\Db\Adapter\Adapter');
$pdo = $dbAdapter->getDriver()->getConnection()->getResource();
if (!$pdo instanceof \PDO) {
throw new ServiceNotCreatedException('Connection resource must be an instance of PDO');
}
return $pdo;
}
}
一旦你有了工厂,只需要将它添加到服务管理器,为Zend\Db\Adapter\Adapter
配置db参数并告诉doctrine使用服务管理器中的现有PdoResource
进行连接。
假设您在一个文件中完成了所有操作,请说dbconn.local.php
...
<?php
return array (
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
// include the pdo resource factory
'PdoResource' => 'Application\Db\Service\PdoResourceFactory',
),
),
// db adapter config
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=database;host=127.0.0.1',
'username' => 'username',
'password' => 'password',
),
'doctrine' => array (
'connection' => array (
'orm_default' => array (
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
// use the resource from the zend adapter
'pdo' => 'PdoResource',
),
),
),
);
答案 1 :(得分:2)
很抱歉将此作为新答案发布,但我无法在Crisp的答案中添加评论,因为我的声誉太低,因为我只注册了stackoverflow撰写此评论:
在Crisp发布的dbconn.local.php
中,请务必将dbname
设置为null
,如下面的代码段所示:
<?php
return array(
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
// the lazy way of Crisp's PdoResourceFactory:
'PdoResource' => function (ServiceLocatorInterface $services) {
$dbAdapter = $services->get('Zend\Db\Adapter\Adapter');
$pdo = $dbAdapter->getDriver()->getConnection()->getResource();
if (!$pdo instanceof \PDO) {
throw new ServiceNotCreatedException('Connection resource must be an instance of PDO');
}
return $pdo;
},
),
),
// db adapter config
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=database;host=127.0.0.1',
'username' => 'username',
'password' => 'password',
),
'doctrine' => array (
'connection' => array (
'orm_default' => array (
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
// use the resource from the zend adapter
'pdo' => 'PdoResource',
// important addition to Crisp's answer:
'params' => array(
'dbname' => null,
),
),
),
),
);
致电
$em->getConnection()->getDatabase();
在您EntityManager
未设置dbname
到null
的情况下,您将获得"database"
作为数据库的名称,因为这是默认值,由您可以看到module.config.php
的{{1}} DoctrineORMModule
here。将dbname
设置为null
会导致扩展Doctrine\DBAL\Driver\PDOMySql\Driver
的{{1}}从数据库本身通过Doctrine\DBAL\Driver\AbstractMySQLDriver
加载数据库的名称,如您所见{ {3}}
同样没有将SELECT DATABASE()
设置为dbname
(或正确的数据库名称)将导致null
的{{1}}函数始终返回false,因为它无法加载当前数据库设置,因为它使用schemaInSyncWithMetadata()
使用Doctrine\ORM\Tools\SchemaValidator
的{{1}},它认为正在使用的数据库被称为Doctrine\ORM\Tools\SchemaTool
。
所以我希望有人可以使用这些信息来节省时间。我浪费了半天才弄明白。
非常感谢Crisp的回答让我节省了很多时间。