diff --git a/docs/en/reference/inheritance-mapping.rst b/docs/en/reference/inheritance-mapping.rst
index 40f50962a..9e895fcbc 100644
--- a/docs/en/reference/inheritance-mapping.rst
+++ b/docs/en/reference/inheritance-mapping.rst
@@ -454,6 +454,7 @@ Things to note:
- This feature is available for all kind of associations. (OneToOne, OneToMany, ManyToOne, ManyToMany)
- The association type *CANNOT* be changed.
- The override could redefine the joinTables or joinColumns depending on the association type.
+- The override could redefine inversedBy to reference more than one extended entity.
Attribute Override
~~~~~~~~~~~~~~~~~~~~
diff --git a/doctrine-mapping.xsd b/doctrine-mapping.xsd
index 6a7e2a284..aef47b2a6 100644
--- a/doctrine-mapping.xsd
+++ b/doctrine-mapping.xsd
@@ -563,11 +563,16 @@
+
+
+
+
+
diff --git a/lib/Doctrine/ORM/Mapping/AssociationOverride.php b/lib/Doctrine/ORM/Mapping/AssociationOverride.php
index 1a9a31f18..83cff4179 100644
--- a/lib/Doctrine/ORM/Mapping/AssociationOverride.php
+++ b/lib/Doctrine/ORM/Mapping/AssociationOverride.php
@@ -50,4 +50,11 @@ final class AssociationOverride implements Annotation
* @var \Doctrine\ORM\Mapping\JoinTable
*/
public $joinTable;
+
+ /**
+ * The name of the association-field on the inverse-side.
+ *
+ * @var string
+ */
+ public $inversedBy;
}
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
index f53999ce8..73f7dc647 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
@@ -2126,6 +2126,10 @@ class ClassMetadataInfo implements ClassMetadata
$mapping['joinColumns'] = $overrideMapping['joinColumns'];
}
+ if (isset($overrideMapping['inversedBy'])) {
+ $mapping['inversedBy'] = $overrideMapping['inversedBy'];
+ }
+
if (isset($overrideMapping['joinTable'])) {
$mapping['joinTable'] = $overrideMapping['joinTable'];
}
diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
index e8af86e84..a4e88dc51 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
@@ -440,6 +440,11 @@ class AnnotationDriver extends AbstractAnnotationDriver
$override['joinTable'] = $joinTable;
}
+ // Check for inversedBy
+ if ($associationOverride->inversedBy) {
+ $override['inversedBy'] = $associationOverride->inversedBy;
+ }
+
$metadata->setAssociationOverride($fieldName, $override);
}
}
diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
index 7f9a7ecc9..0dfbb850e 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
@@ -605,6 +605,11 @@ class XmlDriver extends FileDriver
$override['joinTable'] = $joinTable;
}
+ // Check for inversed-by
+ if (isset($overrideElement->{'inversed-by'})) {
+ $override['inversedBy'] = (string) $overrideElement->{'inversed-by'}['name'];
+ }
+
$metadata->setAssociationOverride($fieldName, $override);
}
}
diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
index aa288d0cd..73fda462d 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
@@ -611,6 +611,11 @@ class YamlDriver extends FileDriver
$override['joinTable'] = $joinTable;
}
+ // Check for inversedBy
+ if (isset($associationOverrideElement['inversedBy'])) {
+ $override['inversedBy'] = (string) $associationOverrideElement['inversedBy'];
+ }
+
$metadata->setAssociationOverride($fieldName, $override);
}
}
diff --git a/tests/Doctrine/Tests/Models/DDC3579/DDC3579Admin.php b/tests/Doctrine/Tests/Models/DDC3579/DDC3579Admin.php
new file mode 100644
index 000000000..cc9803d44
--- /dev/null
+++ b/tests/Doctrine/Tests/Models/DDC3579/DDC3579Admin.php
@@ -0,0 +1,24 @@
+setAssociationOverride('groups', array(
+ 'inversedBy' => 'admins'
+ ));
+ }
+}
diff --git a/tests/Doctrine/Tests/Models/DDC3579/DDC3579Group.php b/tests/Doctrine/Tests/Models/DDC3579/DDC3579Group.php
new file mode 100644
index 000000000..821c06b57
--- /dev/null
+++ b/tests/Doctrine/Tests/Models/DDC3579/DDC3579Group.php
@@ -0,0 +1,70 @@
+name = $name;
+ $this->users = new ArrayCollection();
+ }
+
+ /**
+ * @param string $name
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param DDC3579Admin $admin
+ */
+ public function addAdmin(DDC3579Admin $admin)
+ {
+ $this->admins[] = $admin;
+ }
+
+ /**
+ * @return ArrayCollection
+ */
+ public function getAdmins()
+ {
+ return $this->admins;
+ }
+
+}
+
diff --git a/tests/Doctrine/Tests/Models/DDC3579/DDC3579User.php b/tests/Doctrine/Tests/Models/DDC3579/DDC3579User.php
new file mode 100644
index 000000000..7a7ea5de6
--- /dev/null
+++ b/tests/Doctrine/Tests/Models/DDC3579/DDC3579User.php
@@ -0,0 +1,108 @@
+name = $name;
+ $this->groups = new ArrayCollection;
+ }
+
+ /**
+ * @return integer
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param string $name
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * @param DDC3579Group $group
+ */
+ public function addGroup(DDC3579Group $group)
+ {
+ $this->groups->add($group);
+ $group->addUser($this);
+ }
+
+ /**
+ * @return ArrayCollection
+ */
+ public function getGroups()
+ {
+ return $this->groups;
+ }
+
+ public static function loadMetadata($metadata)
+ {
+ $metadata->mapField(array(
+ 'id' => true,
+ 'fieldName' => 'id',
+ 'type' => 'integer',
+ 'columnName' => 'user_id',
+ 'length' => 150,
+ ));
+
+ $metadata->mapField(array(
+ 'fieldName' => 'name',
+ 'type' => 'string',
+ 'columnName'=> 'user_name',
+ 'nullable' => true,
+ 'unique' => false,
+ 'length' => 250,
+ ));
+
+ $metadata->mapManyToMany(array(
+ 'fieldName' => 'groups',
+ 'targetEntity' => 'DDC3579Group'
+ ));
+
+ $metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadataInfo::GENERATOR_TYPE_AUTO);
+ }
+}
diff --git a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
index 248903c01..19d148b98 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
+++ b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
@@ -664,7 +664,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($personMetadata->name, $mapping['entities'][0]['entityClass']);
}
- /*
+ /*
* @group DDC-964
*/
public function testAssociationOverridesMapping()
@@ -747,6 +747,23 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(array('id'=>'adminaddress_id'), $adminAddress['targetToSourceKeyColumns']);
}
+ /*
+ * @group DDC-3579
+ */
+ public function testInversedByOverrideMapping()
+ {
+
+ $factory = $this->createClassMetadataFactory();
+ $adminMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC3579\DDC3579Admin');
+
+ // assert groups association mappings
+ $this->assertArrayHasKey('groups', $adminMetadata->associationMappings);
+ $adminGroups = $adminMetadata->associationMappings['groups'];
+
+ // assert override
+ $this->assertEquals('admins', $adminGroups['inversedBy']);
+ }
+
/**
* @group DDC-964
*/
@@ -1339,4 +1356,4 @@ class Comment
'columnName' => 'content',
));
}
-}
\ No newline at end of file
+}
diff --git a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC3579.DDC3579Admin.php b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC3579.DDC3579Admin.php
new file mode 100644
index 000000000..dd59e65fa
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC3579.DDC3579Admin.php
@@ -0,0 +1,5 @@
+setAssociationOverride('groups', array(
+ 'inversedBy' => 'admins'
+));
diff --git a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC3579.DDC3579User.php b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC3579.DDC3579User.php
new file mode 100644
index 000000000..1eb3555ec
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC3579.DDC3579User.php
@@ -0,0 +1,27 @@
+mapField(array(
+ 'id' => true,
+ 'fieldName' => 'id',
+ 'type' => 'integer',
+ 'columnName' => 'user_id',
+ 'length' => 150,
+));
+
+$metadata->mapField(array(
+ 'fieldName' => 'name',
+ 'type' => 'string',
+ 'columnName'=> 'user_name',
+ 'nullable' => true,
+ 'unique' => false,
+ 'length' => 250,
+));
+
+$metadata->mapManyToMany(array(
+ 'fieldName' => 'groups',
+ 'targetEntity' => 'DDC3579Group'
+));
+
+$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC3579.DDC3579Admin.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC3579.DDC3579Admin.dcm.xml
new file mode 100644
index 000000000..1f9286706
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC3579.DDC3579Admin.dcm.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC3579.DDC3579User.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC3579.DDC3579User.dcm.xml
new file mode 100644
index 000000000..3b6e213f1
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC3579.DDC3579User.dcm.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC3579.DDC3579Admin.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC3579.DDC3579Admin.dcm.yml
new file mode 100644
index 000000000..7420b14e6
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC3579.DDC3579Admin.dcm.yml
@@ -0,0 +1,5 @@
+Doctrine\Tests\Models\DDC3579\DDC3579Admin:
+ type: entity
+ associationOverride:
+ groups:
+ inversedBy: admins
diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC3579.DDC3579User.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC3579.DDC3579User.dcm.yml
new file mode 100644
index 000000000..63d095035
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC3579.DDC3579User.dcm.yml
@@ -0,0 +1,19 @@
+Doctrine\Tests\Models\DDC3579\DDC3579User:
+ type: mappedSuperclass
+ id:
+ id:
+ type: integer
+ column: user_id
+ length: 150
+ generator:
+ strategy: AUTO
+ fields:
+ name:
+ type: string
+ column: user_name
+ length: 250
+ nullable: true
+ unique: false
+ manyToMany:
+ groups:
+ targetEntity: DDC3579Group