Merge pull request #1308 from z38/override-inversedby
[DDC-3579] Allow override of inversedBy
This commit is contained in:
commit
9e085ca0b3
@ -454,6 +454,7 @@ Things to note:
|
|||||||
- This feature is available for all kind of associations. (OneToOne, OneToMany, ManyToOne, ManyToMany)
|
- This feature is available for all kind of associations. (OneToOne, OneToMany, ManyToOne, ManyToMany)
|
||||||
- The association type *CANNOT* be changed.
|
- The association type *CANNOT* be changed.
|
||||||
- The override could redefine the joinTables or joinColumns depending on the association type.
|
- 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
|
Attribute Override
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -563,11 +563,16 @@
|
|||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="join-table" type="orm:join-table" minOccurs="0" />
|
<xs:element name="join-table" type="orm:join-table" minOccurs="0" />
|
||||||
<xs:element name="join-columns" type="orm:join-columns" minOccurs="0" />
|
<xs:element name="join-columns" type="orm:join-columns" minOccurs="0" />
|
||||||
|
<xs:element name="inversed-by" type="orm:inversed-by-override" minOccurs="0" maxOccurs="1" />
|
||||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="inversed-by-override">
|
||||||
|
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="attribute-overrides">
|
<xs:complexType name="attribute-overrides">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="attribute-override" type="orm:attribute-override" minOccurs="1" maxOccurs="unbounded" />
|
<xs:element name="attribute-override" type="orm:attribute-override" minOccurs="1" maxOccurs="unbounded" />
|
||||||
|
@ -50,4 +50,11 @@ final class AssociationOverride implements Annotation
|
|||||||
* @var \Doctrine\ORM\Mapping\JoinTable
|
* @var \Doctrine\ORM\Mapping\JoinTable
|
||||||
*/
|
*/
|
||||||
public $joinTable;
|
public $joinTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the association-field on the inverse-side.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $inversedBy;
|
||||||
}
|
}
|
||||||
|
@ -2126,6 +2126,10 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
$mapping['joinColumns'] = $overrideMapping['joinColumns'];
|
$mapping['joinColumns'] = $overrideMapping['joinColumns'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($overrideMapping['inversedBy'])) {
|
||||||
|
$mapping['inversedBy'] = $overrideMapping['inversedBy'];
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($overrideMapping['joinTable'])) {
|
if (isset($overrideMapping['joinTable'])) {
|
||||||
$mapping['joinTable'] = $overrideMapping['joinTable'];
|
$mapping['joinTable'] = $overrideMapping['joinTable'];
|
||||||
}
|
}
|
||||||
|
@ -440,6 +440,11 @@ class AnnotationDriver extends AbstractAnnotationDriver
|
|||||||
$override['joinTable'] = $joinTable;
|
$override['joinTable'] = $joinTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for inversedBy
|
||||||
|
if ($associationOverride->inversedBy) {
|
||||||
|
$override['inversedBy'] = $associationOverride->inversedBy;
|
||||||
|
}
|
||||||
|
|
||||||
$metadata->setAssociationOverride($fieldName, $override);
|
$metadata->setAssociationOverride($fieldName, $override);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -605,6 +605,11 @@ class XmlDriver extends FileDriver
|
|||||||
$override['joinTable'] = $joinTable;
|
$override['joinTable'] = $joinTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for inversed-by
|
||||||
|
if (isset($overrideElement->{'inversed-by'})) {
|
||||||
|
$override['inversedBy'] = (string) $overrideElement->{'inversed-by'}['name'];
|
||||||
|
}
|
||||||
|
|
||||||
$metadata->setAssociationOverride($fieldName, $override);
|
$metadata->setAssociationOverride($fieldName, $override);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,6 +611,11 @@ class YamlDriver extends FileDriver
|
|||||||
$override['joinTable'] = $joinTable;
|
$override['joinTable'] = $joinTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for inversedBy
|
||||||
|
if (isset($associationOverrideElement['inversedBy'])) {
|
||||||
|
$override['inversedBy'] = (string) $associationOverrideElement['inversedBy'];
|
||||||
|
}
|
||||||
|
|
||||||
$metadata->setAssociationOverride($fieldName, $override);
|
$metadata->setAssociationOverride($fieldName, $override);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
tests/Doctrine/Tests/Models/DDC3579/DDC3579Admin.php
Normal file
24
tests/Doctrine/Tests/Models/DDC3579/DDC3579Admin.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC3579;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @AssociationOverrides({
|
||||||
|
* @AssociationOverride(
|
||||||
|
* name="groups",
|
||||||
|
* inversedBy="admins"
|
||||||
|
* )
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
class DDC3579Admin extends DDC3579User
|
||||||
|
{
|
||||||
|
public static function loadMetadata($metadata)
|
||||||
|
{
|
||||||
|
$metadata->setAssociationOverride('groups', array(
|
||||||
|
'inversedBy' => 'admins'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
70
tests/Doctrine/Tests/Models/DDC3579/DDC3579Group.php
Normal file
70
tests/Doctrine/Tests/Models/DDC3579/DDC3579Group.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC3579;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC3579Group
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @GeneratedValue
|
||||||
|
* @Id @Column(type="integer")
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ArrayCollection
|
||||||
|
*
|
||||||
|
* @ManyToMany(targetEntity="DDC3579Admin", mappedBy="groups")
|
||||||
|
*/
|
||||||
|
private $admins;
|
||||||
|
|
||||||
|
public function __construct($name = null)
|
||||||
|
{
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
108
tests/Doctrine/Tests/Models/DDC3579/DDC3579User.php
Normal file
108
tests/Doctrine/Tests/Models/DDC3579/DDC3579User.php
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC3579;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @MappedSuperclass
|
||||||
|
*/
|
||||||
|
class DDC3579User
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @GeneratedValue
|
||||||
|
* @Column(type="integer", name="user_id", length=150)
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(name="user_name", nullable=true, unique=false, length=250)
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ArrayCollection
|
||||||
|
*
|
||||||
|
* @ManyToMany(targetEntity="DDC3579Group")
|
||||||
|
*/
|
||||||
|
protected $groups;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function __construct($name = null)
|
||||||
|
{
|
||||||
|
$this->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);
|
||||||
|
}
|
||||||
|
}
|
@ -664,7 +664,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertEquals($personMetadata->name, $mapping['entities'][0]['entityClass']);
|
$this->assertEquals($personMetadata->name, $mapping['entities'][0]['entityClass']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @group DDC-964
|
* @group DDC-964
|
||||||
*/
|
*/
|
||||||
public function testAssociationOverridesMapping()
|
public function testAssociationOverridesMapping()
|
||||||
@ -747,6 +747,23 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertEquals(array('id'=>'adminaddress_id'), $adminAddress['targetToSourceKeyColumns']);
|
$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
|
* @group DDC-964
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$metadata->setAssociationOverride('groups', array(
|
||||||
|
'inversedBy' => 'admins'
|
||||||
|
));
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||||
|
|
||||||
|
$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(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
|
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
|
||||||
|
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||||
|
|
||||||
|
<entity name="Doctrine\Tests\Models\DDC3579\DDC3579Admin">
|
||||||
|
<association-overrides>
|
||||||
|
<association-override name="groups">
|
||||||
|
<inversed-by name="admins" />
|
||||||
|
</association-override>
|
||||||
|
</association-overrides>
|
||||||
|
</entity>
|
||||||
|
|
||||||
|
</doctrine-mapping>
|
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
|
||||||
|
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||||
|
|
||||||
|
<mapped-superclass name="Doctrine\Tests\Models\DDC3579\DDC3579User">
|
||||||
|
<id name="id" type="integer" column="user_id" length="150">
|
||||||
|
<generator strategy="AUTO"/>
|
||||||
|
</id>
|
||||||
|
|
||||||
|
<field name="name" column="user_name" type="string" length="250" nullable="true" unique="false" />
|
||||||
|
|
||||||
|
<many-to-many field="groups" target-entity="DDC3579Group" />
|
||||||
|
</mapped-superclass>
|
||||||
|
|
||||||
|
</doctrine-mapping>
|
@ -0,0 +1,5 @@
|
|||||||
|
Doctrine\Tests\Models\DDC3579\DDC3579Admin:
|
||||||
|
type: entity
|
||||||
|
associationOverride:
|
||||||
|
groups:
|
||||||
|
inversedBy: admins
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user