我有一个带有自己的数据库的Symfony2项目,现在我想连接到另一个数据库(另一个项目),所以我可以修改一些表。
我在config_dev.yml中创建了新连接
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_mysql
host: localhost
dbname: database1
user: root
password:
buv:
driver: pdo_mysql
host: localhost
dbname: database2
user: root
password:
我尝试使用以下命令导入架构:
$ php app / console doctrine:mapping:import --em = buv MyBundle en
[Doctrine \ DBAL \ Schema \ SchemaException]表'old_table'上不存在索引''
但是database2中的一些表没有PK!并且完全导入不起作用。但我只想导入两个表,所以我试过:
$ php app / console doctrine:mapping:import --em = buv --filter =“tablename”MyBundle yml
但我得到了同样的错误,似乎--filter不工作。
控制台命令doctrine:mapping:import中的文档仅表示将实体名称放在过滤器选项中。但我还没有实体。
如果我找到你,你想导入你现有的数据库?
我所做的是:
php app/console doctrine:mapping:convert xml ./src/App/MyBundle/Resources/config/doctrine/metadata/orm --from-database --force
然后选择性转换为注释:
php app/console doctrine:mapping:import AppMyBundle annotation --filter="users_table"
如果您想要yml,请将注释更改为yml。
警告:当您导入到注释或yml时,它将删除您当前的实体文件。
Doctrine要求具有标识符/主键。看看这个页面:http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifiers-primary-keys
但是有一种方法可以从没有主键的表中生成映射和实体。没有主键的表是一种不寻常和错误的数据库设计,但在遗留数据库的情况下存在这种情况。
解: 注意:以下所有参考文献均参考Doctrine 2.0 1.找到文件DatabaseDriver.php(在Doctrine / ORM / Mapping / Driver / DatabaseDriver.php中) 2.找到reverseEngineerMappingFromDatabase方法。修改如下所述的代码。 原始代码是:
private function reverseEngineerMappingFromDatabase()
{
if ($this->tables !== null) {
return;
}
$tables = array();
foreach ($this->_sm->listTableNames() as $tableName) {
$tables[$tableName] = $this->_sm->listTableDetails($tableName);
}
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
foreach ($tables as $tableName => $table) {
/* @var $table \Doctrine\DBAL\Schema\Table */
if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
$foreignKeys = $table->getForeignKeys();
} else {
$foreignKeys = array();
}
$allForeignKeyColumns = array();
foreach ($foreignKeys as $foreignKey) {
$allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
}
if ( ! $table->hasPrimaryKey()) {
throw new MappingException(
"Table " . $table->getName() . " has no primary key. Doctrine does not ".
"support reverse engineering from tables that don't have a primary key."
);
}
$pkColumns = $table->getPrimaryKey()->getColumns();
sort($pkColumns);
sort($allForeignKeyColumns);
if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
$this->manyToManyTables[$tableName] = $table;
} else {
// lower-casing is necessary because of Oracle Uppercase Tablenames,
// assumption is lower-case + underscore separated.
$className = $this->getClassNameForTable($tableName);
$this->tables[$tableName] = $table;
$this->classToTableNames[$className] = $tableName;
}
}
}
修改后的代码是:
private function reverseEngineerMappingFromDatabase()
{
if ($this->tables !== null) {
return;
}
$tables = array();
foreach ($this->_sm->listTableNames() as $tableName) {
$tables[$tableName] = $this->_sm->listTableDetails($tableName);
}
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
foreach ($tables as $tableName => $table) {
/* @var $table \Doctrine\DBAL\Schema\Table */
if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
$foreignKeys = $table->getForeignKeys();
} else {
$foreignKeys = array();
}
$allForeignKeyColumns = array();
foreach ($foreignKeys as $foreignKey) {
$allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
}
$pkColumns=array();
if ($table->hasPrimaryKey()) {
$pkColumns = $table->getPrimaryKey()->getColumns();
sort($pkColumns);
}
sort($allForeignKeyColumns);
if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
$this->manyToManyTables[$tableName] = $table;
} else {
// lower-casing is necessary because of Oracle Uppercase Tablenames,
// assumption is lower-case + underscore separated.
$className = $this->getClassNameForTable($tableName);
$this->tables[$tableName] = $table;
$this->classToTableNames[$className] = $tableName;
}
}
}
3.在同一文件中找到方法loadMetadataForClass。修改如下所述的代码。 找到下面陈述的代码:
try {
$primaryKeyColumns = $this->tables[$tableName]->getPrimaryKey()->getColumns();
} catch(SchemaException $e) {
$primaryKeyColumns = array();
}
像这样修改它:
try {
$primaryKeyColumns = ($this->tables[$tableName]->hasPrimaryKey())?$this->tables[$tableName]->getPrimaryKey()->getColumns():array();
} catch(SchemaException $e) {
$primaryKeyColumns = array();
}
即使对于没有主键的表,上述解决方案也会创建映射(xml / yml / annotation)。
通过在doctrine dbal config中添加schema_filter
,我成功导入了一些数据库实体(~/app/config/config.yml
)
# Doctrine Configuration
doctrine:
dbal:
driver: %database_driver%
host: %database_host%
port: %database_port%
dbname: %database_name%
user: %database_user%
password: %database_password%
charset: UTF8
schema_filter: /^users_table/
app/console doctrine:mapping:import --force MyBundle yml
然后还原config.yml。
我基于简化代码的所有注释创建了一个解决方案
在类名称空间Doctrine \ ORM \ Mapping \ Driver; DatabaseDriver.php
在第277行,更改:
if (!$table->hasPrimaryKey()) {
// comment this Throw exception
// throw new MappingException(
// “Table “ . $table->getName() . “ has no primary key.
// Doctrine does not “.
// “support reverse engineering from tables that don’t
// have a primary key.”
// );
} else {
$pkColumns = $table->getPrimaryKey()->getColumns();
}
并且,在第488行,添加:
if( $table->hasPrimaryKey() ) //add this if to avoid fatalError
return $table->getPrimaryKey()->getColumns();
为避免将来出现任何问题,请在映射数据库后返回设置以避免以后出现任何问题。祝好运!
请注意,命令中的--filter
应填充实体类名称而不是表名称。如果实体尚不存在,则实体类名称必须与您的表名称相符。因此,如果您的表是user_table
,则过滤器值将为UserTable
。
然后,要解决您的数据库有一些Doctrine无法处理的表,您应该将您希望允许Doctrine管理的表列入白名单。您可以在配置文件中执行此操作,如下所示:
doctrine:
dbal:
# ...
schema_filter: /^(users_table|emails)$/
或者你可以在你的cli-config.php文件中指定它。
/** @var Doctrine\ORM\Configuration $config */
$config->setFilterSchemaAssetsExpression('/^(users_table|email)$/');
您必须将getTablePrimaryKeys函数更新为:
private function getTablePrimaryKeys(Table $table)
{
try {
$primaryKeyColumns = ($this->tables[$table->getName()]->hasPrimaryKey())?$this->tables[$table->getName()]->getPrimaryKey()->getColumns():array();
} catch(SchemaException $e) {
$primaryKeyColumns = array();
}
return array();
}
在DatabaseDriver.php文件中,您可以更改reverseEngineerMappingFromDatabase函数
throw new MappingException("Table " . $table->getName() . " has no primary key. Doctrine does not "."support reverse engineering from tables that don't have a primary key.");
同
if(! $table->hasColumn('id')){
$table->addColumn('id', 'integer', array('autoincrement' => true));
}
$table->setPrimaryKey(array('id'));
php bin/console doctrine:mapping:convert xml ./src/NameBundle/Resources/doctrine/metadata/orm
php bin/console doctrine:mapping:import NameBundle yml
php bin/console doctrine:generate:entities NameBundle