Importing tables from external database in Symfony2 with doctrine

前端 未结 8 876
醉酒成梦
醉酒成梦 2020-12-12 18:18

I have a Symfony2 project with its own database, and now I want to connect to another database (another project) so I can modify some tables.

I created the new conne

相关标签:
8条回答
  • 2020-12-12 18:53

    I've successfully imported some database entities by adding a schema_filter in the doctrine dbal config (~/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

    Then revert config.yml.

    0 讨论(0)
  • 2020-12-12 18:58

    I created a solution based on all comments that simplifies the code

    on class namespace Doctrine\ORM\Mapping\Driver; DatabaseDriver.php

    On line 277, change:

    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();
    }
    

    And, on line 488, add:

    if( $table->hasPrimaryKey() ) //add this if to avoid fatalError
     return $table->getPrimaryKey()->getColumns();
    

    To avoid any future problems, after mapping your database, return the settings to avoid any problems later. Good luck!

    0 讨论(0)
  • 2020-12-12 18:58

    At the DatabaseDriver.php file reverseEngineerMappingFromDatabase function you can change

    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.");
    

    with

    if(! $table->hasColumn('id')){
       $table->addColumn('id', 'integer', array('autoincrement' => true));
    }
       $table->setPrimaryKey(array('id'));
    
    0 讨论(0)
  • 2020-12-12 19:02

    It is a requirement for Doctrine to have an identifier/primary key. Take a look at this page: http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifiers-primary-keys

    But there is a way to generate mappings and entities from tables that do not have a primary key. A table with no primary key is an unusual and bad database design but such a scenario exists in case of legacy databases.

    Solution:
    Note: All references below refer to Doctrine 2.0
    1. Find the file DatabaseDriver.php (in Doctrine/ORM/Mapping/Driver/DatabaseDriver.php)
    2. Find the method reverseEngineerMappingFromDatabase. Modify the code as stated below.
    The original code is:

    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;
                }
            }
        }
    


    The modified code is:

    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. Find the method loadMetadataForClass in the same file. Modify the code as stated below.
    Find the code stated below:

    try {
       $primaryKeyColumns = $this->tables[$tableName]->getPrimaryKey()->getColumns();
    } catch(SchemaException $e) {
        $primaryKeyColumns = array();
    }
    


    Modify it like this:

    try {
         $primaryKeyColumns = ($this->tables[$tableName]->hasPrimaryKey())?$this->tables[$tableName]->getPrimaryKey()->getColumns():array();
    } catch(SchemaException $e) {
         $primaryKeyColumns = array();
    }
    



    The above solution creates mappings(xml/yml/annotation) even for tables that don't have a primary key.

    0 讨论(0)
  • 2020-12-12 19:03

    If I get you correctly, you want to import your existing database?

    What I do is:

    php app/console doctrine:mapping:convert xml ./src/App/MyBundle/Resources/config/doctrine/metadata/orm --from-database --force
    

    Then do a selective convert to annotation:

    php app/console doctrine:mapping:import AppMyBundle annotation --filter="users_table"
    

    If you wanted to yml, change annotation to yml.

    warning: when you import to annotation or yml, it will delete your current entity file.

    0 讨论(0)
  • 2020-12-12 19:06
    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
    
    0 讨论(0)
提交回复
热议问题