Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It is a requirement for Doctrine to <strong>have an identifier/primary key</strong>. Take a look at this page: <a href="http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifiers-primary-keys" rel="nofollow">http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifiers-primary-keys</a></p> <p>But there <strong>is a way to generate mappings and entities from tables that do not have a primary key</strong>. A table with no primary key is an unusual and bad database design but such a scenario exists in case of legacy databases.</p> <p><strong>Solution</strong>:<br /> <strong>Note</strong>: All references below refer to Doctrine 2.0 <br /> 1. Find the file <strong>DatabaseDriver.php</strong> (in Doctrine/ORM/Mapping/Driver/DatabaseDriver.php)<br /> 2. Find the method <strong>reverseEngineerMappingFromDatabase</strong>. Modify the code as stated below. <br />The original code is: <br /></p> <pre><code>private function reverseEngineerMappingFromDatabase() { if ($this-&gt;tables !== null) { return; } $tables = array(); foreach ($this-&gt;_sm-&gt;listTableNames() as $tableName) { $tables[$tableName] = $this-&gt;_sm-&gt;listTableDetails($tableName); } $this-&gt;tables = $this-&gt;manyToManyTables = $this-&gt;classToTableNames = array(); foreach ($tables as $tableName =&gt; $table) { /* @var $table \Doctrine\DBAL\Schema\Table */ if ($this-&gt;_sm-&gt;getDatabasePlatform()-&gt;supportsForeignKeyConstraints()) { $foreignKeys = $table-&gt;getForeignKeys(); } else { $foreignKeys = array(); } $allForeignKeyColumns = array(); foreach ($foreignKeys as $foreignKey) { $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey-&gt;getLocalColumns()); } if ( ! $table-&gt;hasPrimaryKey()) { throw new MappingException( "Table " . $table-&gt;getName() . " has no primary key. Doctrine does not ". "support reverse engineering from tables that don't have a primary key." ); } $pkColumns = $table-&gt;getPrimaryKey()-&gt;getColumns(); sort($pkColumns); sort($allForeignKeyColumns); if ($pkColumns == $allForeignKeyColumns &amp;&amp; count($foreignKeys) == 2) { $this-&gt;manyToManyTables[$tableName] = $table; } else { // lower-casing is necessary because of Oracle Uppercase Tablenames, // assumption is lower-case + underscore separated. $className = $this-&gt;getClassNameForTable($tableName); $this-&gt;tables[$tableName] = $table; $this-&gt;classToTableNames[$className] = $tableName; } } } </code></pre> <p><br /> The modified code is: <br /></p> <pre><code>private function reverseEngineerMappingFromDatabase() { if ($this-&gt;tables !== null) { return; } $tables = array(); foreach ($this-&gt;_sm-&gt;listTableNames() as $tableName) { $tables[$tableName] = $this-&gt;_sm-&gt;listTableDetails($tableName); } $this-&gt;tables = $this-&gt;manyToManyTables = $this-&gt;classToTableNames = array(); foreach ($tables as $tableName =&gt; $table) { /* @var $table \Doctrine\DBAL\Schema\Table */ if ($this-&gt;_sm-&gt;getDatabasePlatform()-&gt;supportsForeignKeyConstraints()) { $foreignKeys = $table-&gt;getForeignKeys(); } else { $foreignKeys = array(); } $allForeignKeyColumns = array(); foreach ($foreignKeys as $foreignKey) { $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey-&gt;getLocalColumns()); } $pkColumns=array(); if ($table-&gt;hasPrimaryKey()) { $pkColumns = $table-&gt;getPrimaryKey()-&gt;getColumns(); sort($pkColumns); } sort($allForeignKeyColumns); if ($pkColumns == $allForeignKeyColumns &amp;&amp; count($foreignKeys) == 2) { $this-&gt;manyToManyTables[$tableName] = $table; } else { // lower-casing is necessary because of Oracle Uppercase Tablenames, // assumption is lower-case + underscore separated. $className = $this-&gt;getClassNameForTable($tableName); $this-&gt;tables[$tableName] = $table; $this-&gt;classToTableNames[$className] = $tableName; } } } </code></pre> <p><br /> 3. Find the method <strong>loadMetadataForClass</strong> in the same file. Modify the code as stated below. <br /> Find the code stated below: <br /></p> <pre><code>try { $primaryKeyColumns = $this-&gt;tables[$tableName]-&gt;getPrimaryKey()-&gt;getColumns(); } catch(SchemaException $e) { $primaryKeyColumns = array(); } </code></pre> <p><br /> Modify it like this: <br /></p> <pre><code>try { $primaryKeyColumns = ($this-&gt;tables[$tableName]-&gt;hasPrimaryKey())?$this-&gt;tables[$tableName]-&gt;getPrimaryKey()-&gt;getColumns():array(); } catch(SchemaException $e) { $primaryKeyColumns = array(); } </code></pre> <p><br /><br /> The above <strong>solution creates mappings(xml/yml/annotation) even for tables that don't have a primary key</strong>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload