使用一个数据库连接的zf2 doctrine2和Zend \ Db \ Adapter \ Adapter

时间:2014-01-12 07:04:32

标签: doctrine-orm zend-framework2

我使用doctrine2和ZF2,我的一些库使用Zend \ Db \ Adapter \ Adapter,其他库使用doctrine2。现在,他们连接到数据库两次。是否可以在doctrine和标准ZF2 db adapter中使用一个db连接?

2 个答案:

答案 0 :(得分:10)

DoctrineORM模块接受PDO资源或服务名称,其中实例可以位于服务管理器中,而不是通常的连接参数。

第一步是创建一个服务工厂,从Zend\Db\Adapter\Adapter服务

中检索PDO资源
<?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,如下面的代码段所示:

除了Crisp的回答:

<?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未设置dbnamenull的情况下

,您将获得"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的回答让我节省了很多时间。