From fa79de6ea43ee59aeaa08009ca3f0c31615e92b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20St=C3=B6ckl?= Date: Thu, 13 Mar 2014 16:47:22 +0100 Subject: [PATCH 1/4] Enable empty prefixes for inlined embeddable This fixes http://www.doctrine-project.org/jira/browse/DDC-2987 This makes it possible to map a field from an embeddable to a database field with the same name, without any prefix added. Example: - an embeddable object "Id" with a property "id" - per default this would map inline to id_id - supplying null or '' as columnPrefix does not work due to the ! empty() check - with my little change, if columnPrefix : false is supplied in the mapping config this will now map to a db column "id" To build Ids as ValueObjects is a very common approach in DDD, so ihmo this is a must have. --- lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index 8770cb4ac..50dc3baa3 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -3187,7 +3187,7 @@ class ClassMetadataInfo implements ClassMetadata $fieldMapping['originalField'] = $fieldMapping['fieldName']; $fieldMapping['fieldName'] = $property . "." . $fieldMapping['fieldName']; - $fieldMapping['columnName'] = ! empty($this->embeddedClasses[$property]['columnPrefix']) + $fieldMapping['columnName'] = ! empty($this->embeddedClasses[$property]['columnPrefix']) || $this->embeddedClasses[$property]['columnPrefix'] === false ? $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName'] : $this->namingStrategy->embeddedFieldToColumnName($property, $fieldMapping['columnName'], $this->reflClass->name, $embeddable->reflClass->name); From cd2043915cc75e621f66879c921859bd640d972e Mon Sep 17 00:00:00 2001 From: Anton Stoeckl Date: Fri, 14 Mar 2014 12:29:01 +0100 Subject: [PATCH 2/4] columnPrefix must support string and boolean, so changing to mixed --- .../ORM/Mapping/ClassMetadataInfo.php | 19 +++- lib/Doctrine/ORM/Mapping/Embedded.php | 2 +- .../Tests/ORM/Functional/ValueObjectsTest.php | 104 ++++++++++++++++++ 3 files changed, 121 insertions(+), 4 deletions(-) diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index 50dc3baa3..3de7a5c46 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -3158,6 +3158,7 @@ class ClassMetadataInfo implements ClassMetadata * Map Embedded Class * * @param array $mapping + * @throws MappingException * @return void */ public function mapEmbedded(array $mapping) @@ -3187,9 +3188,21 @@ class ClassMetadataInfo implements ClassMetadata $fieldMapping['originalField'] = $fieldMapping['fieldName']; $fieldMapping['fieldName'] = $property . "." . $fieldMapping['fieldName']; - $fieldMapping['columnName'] = ! empty($this->embeddedClasses[$property]['columnPrefix']) || $this->embeddedClasses[$property]['columnPrefix'] === false - ? $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName'] - : $this->namingStrategy->embeddedFieldToColumnName($property, $fieldMapping['columnName'], $this->reflClass->name, $embeddable->reflClass->name); + if (! empty($this->embeddedClasses[$property]['columnPrefix'])) { + $fieldMapping['columnName'] = $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName']; + } elseif ($this->embeddedClasses[$property]['columnPrefix'] !== false) { + $fieldMapping['columnName'] = $this->namingStrategy + ->embeddedFieldToColumnName( + $property, + $fieldMapping['columnName'], + $this->reflClass->name, + $embeddable->reflClass->name + ); + } + +// $fieldMapping['columnName'] = ! empty($this->embeddedClasses[$property]['columnPrefix']) || $this->embeddedClasses[$property]['columnPrefix'] === false +// ? $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName'] +// : $this->namingStrategy->embeddedFieldToColumnName($property, $fieldMapping['columnName'], $this->reflClass->name, $embeddable->reflClass->name); $this->mapField($fieldMapping); } diff --git a/lib/Doctrine/ORM/Mapping/Embedded.php b/lib/Doctrine/ORM/Mapping/Embedded.php index b44bced84..37339108b 100644 --- a/lib/Doctrine/ORM/Mapping/Embedded.php +++ b/lib/Doctrine/ORM/Mapping/Embedded.php @@ -32,7 +32,7 @@ final class Embedded implements Annotation public $class; /** - * @var string + * @var mixed */ public $columnPrefix; } diff --git a/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php b/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php index 40768f35c..5f49c9a90 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php @@ -179,8 +179,46 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC93PhoneNumber') )); } + + + + public function testInlineEmbeddableWithPrefix() + { + $expectedColumnName = 'foobar_id'; + + $actualColumnName = $this->_em + ->getClassMetadata(__NAMESPACE__ . '\DDC3028PersonWithPrefix') + ->getColumnName('id.id'); + + $this->assertEquals($expectedColumnName, $actualColumnName); + } + + public function testInlineEmbeddableEmptyPrefix() + { + $expectedColumnName = 'id_id'; + + $actualColumnName = $this->_em + ->getClassMetadata(__NAMESPACE__ . '\DDC3028PersonEmptyPrefix') + ->getColumnName('id.id'); + + $this->assertEquals($expectedColumnName, $actualColumnName); + } + + public function testInlineEmbeddablePrefixFalse() + { + $expectedColumnName = 'id'; + + $actualColumnName = $this->_em + ->getClassMetadata(__NAMESPACE__ . '\DDC3028PersonPrefixFalse') + ->getColumnName('id.id'); + + $this->assertEquals($expectedColumnName, $actualColumnName); + } + + } + /** * @Entity */ @@ -296,3 +334,69 @@ class DDC93ContactInfo /** @Embedded(class = "DDC93Address") */ private $address; } + +/** + * @Entity + */ +class DDC3028PersonWithPrefix +{ + const CLASSNAME = __CLASS__; + + /** @Embedded(class="DDC3028Id", columnPrefix = "foobar_") */ + public $id; + + public function __construct(DDC3028Id $id = null) + { + $this->id = $id; + } +} + +/** + * @Entity + */ +class DDC3028PersonEmptyPrefix +{ + const CLASSNAME = __CLASS__; + + /** @Embedded(class="DDC3028Id", columnPrefix = "") */ + public $id; + + public function __construct(DDC3028Id $id = null) + { + $this->id = $id; + } +} + +/** + * @Entity + */ +class DDC3028PersonPrefixFalse +{ + const CLASSNAME = __CLASS__; + + /** @Embedded(class="DDC3028Id", columnPrefix = false) */ + public $id; + + public function __construct(DDC3028Id $id = null) + { + $this->id = $id; + } +} + +/** + * @Embeddable + */ +class DDC3028Id +{ + const CLASSNAME = __CLASS__; + + /** + * @Id @Column(type="string") + */ + public $id; + + public function __construct($id = null) + { + $this->id = $id; + } +} From 871dc5d186d8131e48368585354a5109357f1316 Mon Sep 17 00:00:00 2001 From: Anton Stoeckl Date: Fri, 14 Mar 2014 12:32:49 +0100 Subject: [PATCH 3/4] Test are for fix of ticket DDC-3028 Added 3 tests that check regression for: - columnPrefix is empty - columnPrefix is a string - columnPrefix is false Added some small entity / embeddable classes to support the test cases. --- tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php b/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php index 5f49c9a90..8820fe501 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php @@ -180,8 +180,6 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase )); } - - public function testInlineEmbeddableWithPrefix() { $expectedColumnName = 'foobar_id'; @@ -214,8 +212,6 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals($expectedColumnName, $actualColumnName); } - - } From 83ef47c8d0d603ea1d7352c64d92674b568d2693 Mon Sep 17 00:00:00 2001 From: Anton Stoeckl Date: Fri, 14 Mar 2014 12:34:22 +0100 Subject: [PATCH 4/4] This fixes ticket DDC-3028 Enables columnPrefix to be "false" so no prefix is added. Changed the structure a bit (to if/else) to be more readable with the additional condition. --- lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index 3de7a5c46..62ea7bb9b 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -3200,10 +3200,6 @@ class ClassMetadataInfo implements ClassMetadata ); } -// $fieldMapping['columnName'] = ! empty($this->embeddedClasses[$property]['columnPrefix']) || $this->embeddedClasses[$property]['columnPrefix'] === false -// ? $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName'] -// : $this->namingStrategy->embeddedFieldToColumnName($property, $fieldMapping['columnName'], $this->reflClass->name, $embeddable->reflClass->name); - $this->mapField($fieldMapping); } }