diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index ec7023075..3eb60e87c 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -42,6 +42,7 @@ use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; * @author Jonathan Wage * @author Roman Borschel * @author Benjamin Eberlei + * @author Stefano Rodriguez */ class SchemaTool { @@ -142,6 +143,9 @@ class SchemaTool $metadataSchemaConfig->setExplicitForeignKeyIndexes(false); $schema = new Schema(array(), array(), $metadataSchemaConfig); + $addedFks = array(); + $blacklistedFks = array(); + foreach ($classes as $class) { if ($this->processingNotRequired($class, $processedClasses)) { continue; @@ -150,8 +154,8 @@ class SchemaTool $table = $schema->createTable($this->quoteStrategy->getTableName($class, $this->platform)); if ($class->isInheritanceTypeSingleTable()) { - $this->gatherColumns($class, $table); - $this->gatherRelationsSql($class, $table, $schema); + $columns = $this->gatherColumns($class, $table); + $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); // Add the discriminator column $this->addDiscriminatorColumnDefinition($class, $table); @@ -165,7 +169,7 @@ class SchemaTool foreach ($class->subClasses as $subClassName) { $subClass = $this->em->getClassMetadata($subClassName); $this->gatherColumns($subClass, $table); - $this->gatherRelationsSql($subClass, $table, $schema); + $this->gatherRelationsSql($subClass, $table, $schema, $addedFks, $blacklistedFks); $processedClasses[$subClassName] = true; } } elseif ($class->isInheritanceTypeJoined()) { @@ -182,7 +186,7 @@ class SchemaTool } } - $this->gatherRelationsSql($class, $table, $schema); + $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); // Add the discriminator column only to the root table if ($class->name == $class->rootEntityName) { @@ -211,7 +215,7 @@ class SchemaTool throw ORMException::notSupported(); } else { $this->gatherColumns($class, $table); - $this->gatherRelationsSql($class, $table, $schema); + $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); } $pkColumns = array(); @@ -432,9 +436,11 @@ class SchemaTool * @param ClassMetadata $class * @param \Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Schema\Schema $schema + * @param array $addedFks + * @param array $blacklistedFks * @return void */ - private function gatherRelationsSql($class, Table $table, $schema) + private function gatherRelationsSql($class, $table, $schema, &$addedFks, &$blacklistedFks) { foreach ($class->associationMappings as $mapping) { if (isset($mapping['inherited'])) { @@ -446,7 +452,7 @@ class SchemaTool if ($mapping['type'] & ClassMetadata::TO_ONE && $mapping['isOwningSide']) { $primaryKeyColumns = $uniqueConstraints = array(); // PK is unnecessary for this relation-type - $this->_gatherRelationJoinColumns($mapping['joinColumns'], $table, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints); + $this->_gatherRelationJoinColumns($mapping['joinColumns'], $table, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints, $addedFks, $blacklistedFks); foreach($uniqueConstraints as $indexName => $unique) { $table->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName); @@ -463,10 +469,10 @@ class SchemaTool $primaryKeyColumns = $uniqueConstraints = array(); // Build first FK constraint (relation table => source table) - $this->_gatherRelationJoinColumns($joinTable['joinColumns'], $theJoinTable, $class, $mapping, $primaryKeyColumns, $uniqueConstraints); + $this->_gatherRelationJoinColumns($joinTable['joinColumns'], $theJoinTable, $class, $mapping, $primaryKeyColumns, $uniqueConstraints, $addedFks, $blacklistedFks); // Build second FK constraint (relation table => target table) - $this->_gatherRelationJoinColumns($joinTable['inverseJoinColumns'], $theJoinTable, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints); + $this->_gatherRelationJoinColumns($joinTable['inverseJoinColumns'], $theJoinTable, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints, $addedFks, $blacklistedFks); $theJoinTable->setPrimaryKey($primaryKeyColumns); @@ -522,8 +528,10 @@ class SchemaTool * @param array $mapping * @param array $primaryKeyColumns * @param array $uniqueConstraints + * @param array $addedFks + * @param array $blacklistedFks */ - private function _gatherRelationJoinColumns($joinColumns, $theJoinTable, $class, $mapping, &$primaryKeyColumns, &$uniqueConstraints) + private function _gatherRelationJoinColumns($joinColumns, $theJoinTable, $class, $mapping, &$primaryKeyColumns, &$uniqueConstraints, &$addedFks, &$blacklistedFks) { $localColumns = array(); $foreignColumns = array(); @@ -587,9 +595,27 @@ class SchemaTool } } - $theJoinTable->addForeignKeyConstraint( - $foreignTableName, $localColumns, $foreignColumns, $fkOptions - ); + $compositeName = $theJoinTable->getName().'.'.implode('', $localColumns); + if (isset($addedFks[$compositeName]) + && ($foreignTableName != $addedFks[$compositeName]['foreignTableName'] + || 0 < count(array_diff($foreignColumns, $addedFks[$compositeName]['foreignColumns']))) + ) { + foreach ($theJoinTable->getForeignKeys() as $fkName => $key) { + if (0 === count(array_diff($key->getLocalColumns(), $localColumns)) + && (($key->getForeignTableName() != $foreignTableName) + || 0 < count(array_diff($key->getForeignColumns(), $foreignColumns))) + ) { + $theJoinTable->removeForeignKey($fkName); + break; + } + } + $blacklistedFks[$compositeName] = true; + } elseif (!isset($blacklistedFks[$compositeName])) { + $addedFks[$compositeName] = array('foreignTableName' => $foreignTableName, 'foreignColumns' => $foreignColumns); + $theJoinTable->addUnnamedForeignKeyConstraint( + $foreignTableName, $localColumns, $foreignColumns, $fkOptions + ); + } } /** diff --git a/tests/Doctrine/Tests/Models/SingleTableInheritanceType/Structure.php b/tests/Doctrine/Tests/Models/SingleTableInheritanceType/Structure.php index 6be981aeb..26c577c51 100755 --- a/tests/Doctrine/Tests/Models/SingleTableInheritanceType/Structure.php +++ b/tests/Doctrine/Tests/Models/SingleTableInheritanceType/Structure.php @@ -8,15 +8,15 @@ namespace Doctrine\Tests\Models\SingleTableInheritanceType; */ class Structure { - /** - * @Id - * @Column(type="integer") - * @GeneratedValue(strategy="AUTO") - */ - protected $id; + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + protected $id; - /** - * @Column(type="string", length=32, nullable=true) - */ - protected $name; + /** + * @Column(type="string", length=32, nullable=true) + */ + protected $name; } diff --git a/tests/Doctrine/Tests/Models/SingleTableInheritanceType/User.php b/tests/Doctrine/Tests/Models/SingleTableInheritanceType/User.php index 26bf14688..8af0170cb 100755 --- a/tests/Doctrine/Tests/Models/SingleTableInheritanceType/User.php +++ b/tests/Doctrine/Tests/Models/SingleTableInheritanceType/User.php @@ -10,17 +10,17 @@ use Doctrine\Common\Collections\ArrayCollection; */ class User { - /** - * @Id - * @Column(type="integer") - * @GeneratedValue(strategy="AUTO") - */ - protected $id; + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + protected $id; - /** - * @Column(type="string", length=32, nullable=true) - */ - protected $name; + /** + * @Column(type="string", length=32, nullable=true) + */ + protected $name; /** * @var ArrayCollection $followedUsers @@ -34,7 +34,8 @@ class User */ protected $followedStructures; - public function __construct() { + public function __construct() + { $this->followedUsers = new ArrayCollection(); $this->followedStructures = new ArrayCollection(); } @@ -52,7 +53,7 @@ class User /** * Add followedUsers * - * @param UserFollowedUser $followedUsers + * @param UserFollowedUser $followedUsers * @return User */ public function addFollowedUser(UserFollowedUser $followedUsers) @@ -65,7 +66,7 @@ class User /** * Remove followedUsers * - * @param UserFollowedUser $followedUsers + * @param UserFollowedUser $followedUsers * @return User */ public function removeFollowedUser(UserFollowedUser $followedUsers) @@ -88,7 +89,7 @@ class User /** * Add followedStructures * - * @param UserFollowedStructure $followedStructures + * @param UserFollowedStructure $followedStructures * @return User */ public function addFollowedStructure(UserFollowedStructure $followedStructures) @@ -101,7 +102,7 @@ class User /** * Remove followedStructures * - * @param UserFollowedStructure $followedStructures + * @param UserFollowedStructure $followedStructures * @return User */ public function removeFollowedStructure(UserFollowedStructure $followedStructures) diff --git a/tests/Doctrine/Tests/Models/SingleTableInheritanceType/UserFollowedStructure.php b/tests/Doctrine/Tests/Models/SingleTableInheritanceType/UserFollowedStructure.php index 8ee0888cf..8648407da 100755 --- a/tests/Doctrine/Tests/Models/SingleTableInheritanceType/UserFollowedStructure.php +++ b/tests/Doctrine/Tests/Models/SingleTableInheritanceType/UserFollowedStructure.php @@ -24,7 +24,7 @@ class UserFollowedStructure extends UserFollowedObject /** * Construct a UserFollowedStructure entity * - * @param User $user + * @param User $user * @param Structure $followedStructure */ public function __construct(User $user, Structure $followedStructure)