使用 Doctrine2 和 PostgreSQL 进行多数据库模式和迁移
Posted
技术标签:
【中文标题】使用 Doctrine2 和 PostgreSQL 进行多数据库模式和迁移【英文标题】:Multiple DB Schema & migrations with Doctrine2 & PostgreSQL 【发布时间】:2015-12-29 16:22:11 【问题描述】:我有一个包含多个模式的 PG 数据库。
我有一个 symfony2 应用程序,它只需要连接其中一个。
如果我没有配置任何东西,默认情况下,Doctrine2 会搜索所有模式,因此它会尝试在它不正确的表上创建 SELECT
。
我关注了这个答案:symfony2 + doctrine2@postgresql setting a schema
现在它似乎只出现在我指定的 shema 中,但它仍在寻找一些在我的架构中不存在但在其他架构中存在的表。
当我执行一些 ldoctrine:migrations:diff
[Doctrine\DBAL\DBALException]
An exception occurred while executing 'SELECT min_value, increment_by FROM "pgstatspacknameid"':
SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "pgstatspacknameid" does not exist
LINE 1: SELECT min_value, increment_by FROM "pgstatspacknameid"
^
[PDOException]
SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "pgstatspacknameid" does not exist
LINE 1: SELECT min_value, increment_by FROM "pgstatspacknameid"
^
所以按照学说迁移文档,我在连接配置中添加了这一行:
schema_filter: ~^(?!pgstats)~
它仍然总是尝试在那些表中创建SELECT
...
【问题讨论】:
【参考方案1】:迁移命令需要选项 --db-configuration。 它需要一个配置文件作为参数。 尝试使用配置文件的以下内容。
<?php
return array(
"driverClass"=>"AppBundle\Driver",
"host" => "localhost",
"user" => "test",
"password" => "test",
"dbname" => "test"
);
?>
此外,我更改了 vendor/doctrine/dbal/lib/Doctrine/DBAL/SchemaPostgreSqlSchemaManager.php 以始终将模式添加到序列名称之前。
像这样:
/**
* @inheritdoc
*/
protected function _getPortableSequencesList($sequences)
$sequenceDefinitions = array();
foreach ($sequences as $sequence) //+ || true
if ($sequence['schemaname'] != 'public' || true)
$sequenceName = $sequence['schemaname'] . "." . $sequence['relname'];
else
$sequenceName = $sequence['relname'];
$sequenceDefinitions[$sequenceName] = $sequence;
$list = array();
foreach ($this->filterAssetNames(array_keys($sequenceDefinitions)) as $sequenceName)
$list[] = $this->_getPortableSequenceDefinition($sequenceDefinitions[$sequenceName]);
return $list;
/**
* @inheritdoc
*/
protected function getPortableNamespaceDefinition(array $namespace)
return $namespace['nspname'];
/**
* @inheritdoc
*/
protected function _getPortableSequenceDefinition($sequence)
//+ || true
if ($sequence['schemaname'] != 'public' || true)
$sequenceName = $sequence['schemaname'] . "." . $sequence['relname'];
else
$sequenceName = $sequence['relname'];
$data = $this->_conn->fetchAll('SELECT min_value, increment_by FROM ' . $this->_platform->quoteIdentifier($sequenceName));
return new Sequence($sequenceName, $data[0]['increment_by'], $data[0]['min_value']);
(在假定架构名称 != 'public' 的地方添加了 or true 两个地方)
【讨论】:
谢谢我要测试这个解决方案!您知道如何在不更改 vendor 文件的情况下覆盖此类吗? 未测试,但您可以从 AbstractPostgresqlDriver 覆盖 getSchemaManager 以返回具有上述更改的自定义 SchemaManager。以上是关于使用 Doctrine2 和 PostgreSQL 进行多数据库模式和迁移的主要内容,如果未能解决你的问题,请参考以下文章
如何使Doctrine PostgreSQL外键约束DEFERRABLE
Doctrine2:使用 NativeQuery 和 ResultSetMapping 进行查询
Doctrine2.2 (sqlite using memory) 使用 OrmTestCase 和 phpUnit TroubleShoot