2011-07-01 70 views
22

我有一個Symfony2項目與自己的數據庫,現在我想連接到另一個數據庫(另一個項目),所以我可以修改一些表。從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應用程序/控制檯學說:映射:進口--em = BUV MyBundle YML

[學說\ DBAL \架構\ SchemaException] 索引 'OLD_TABLE' 不上表中存在 ''

但是database2中的一些表沒有PK!全部進口無效。但我只想要導入兩個表,所以我嘗試:

$ PHP應用程序/控制檯學說:映射:進口--em = BUV --filter = 「表名」 MyBundle陽明

但我得到同樣的錯誤,似乎 - 過濾器不起作用。

控制檯命令doctrine:mapping:import中的文檔只說要將實體名稱放在過濾器選項中。但我還沒有一個實體。

回答

12

如果我正確地得到你,你想導入你現有的數據庫?

我要做的就是:

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時,它會刪除您當前的實體文件。

+4

,你認爲第一個命令似乎並沒有因爲我的表的一個工作沒有PK。這是如何解決它的? –

+0

試着寫過濾參數駱駝的情況下開始與大字母,即: PHP應用程序/控制檯學說:映射:進口AppMyBundle陽明--filter =「UsersTable」 – ezpn

+1

當我有這個問題,--filter似乎不應用。還不能解決它。 – hugofcampos

15

這是一個要求,學說有一個標識符/主鍵。 看看這個頁面:http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifiers-primary-keys

但有一種方法來生成表的映射和實體沒有一個主鍵。沒有主鍵的表是一種不尋常的和不良的數據庫設計,但是在遺留數據庫的情況下存在這種情況。


:下面的所有參考學說2.0
1.查找文件DatabaseDriver.php(在學說/ ORM /映射/驅動程序/ 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 /註釋)即使對於表,唐沒有主鍵。

+0

IM我的文件中,有沒有這樣的線路存在其中U在'loadMetadataForClass'方法 – Hunt

+1

提到這一點適用於教義2.X版本 –

+0

'私有函數getTablePrimaryKeys(表$表) { 嘗試{$ = primaryKeyColumns($此 - >表[$表 - >的getName()] - > hasPrimaryKey())$這 - >表[$表 - >的getName()] - >的getPrimaryKey() - > getColumns():?陣列(); (SchemaException $ e){ $ primaryKeyColumns = array(); } return array(); }' – bstricks

1

你必須更新getTablePrimaryKeys功能:

​​
3

我創建了基於這樣簡化了代碼

階級 命名空間學說\ ORM \製圖\驅動器的所有意見的解決方案; 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(); 

爲了避免將來出現問題,映射數據庫後,設置返回以後避免任何問題。 祝你好運!

+1

對不起,評論一箇舊的帖子,但我碰到了今晚的問題,對我來說,這個解決方案拋出了一個異常,所以我在'if'條件中添加了'$ pkColumns = array();'並且不需要請在第488行添加該部分。非常感謝。 – gabtzi

+0

Doctrine 2.5.5的更新:第一個改變現在在第287行(函數'reverseEngineerMappingFromDatabase()'),第二個改變在第507行(函數'getTablePrimaryKeys()') – Shady

4

我已經成功地通過在學說DBAL配置添加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進口了一些數據庫實體。

+0

這對我很有用。謝謝! – Jotaeme

+0

'schema_filter'在Oracle數據庫上運行良好,謝謝 –

+0

謝謝!在Postgres DB上正常工作 – Xander

3

注意--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)$/'); 
0
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 
我有同樣的問題