Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

#194 toOne handles fieldset arrays nicely #195

Closed
wants to merge 8 commits into from

2 participants

@texdc

Fix for issue #194.

@Ocramius
Owner

@texdc I'm really late on this one, sorry :(
Any chance to get a rebase (for convenience, you should squash it before rebasing) and then add docs to it?

@texdc
@texdc

@Ocramius it looks like I got my rebase before my squash. Sorry.

@Ocramius
Owner

@texdc you didn't rebase, you merged master into it :( I'll try to extract relevant

@texdc

Sorry about that. It was late. I'll learn from it and the next PR won't be such a mess.

@Ocramius
Owner

@texdc no problem

@texdc texdc closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 17, 2013
  1. @texdc
  2. @texdc
  3. @texdc
Commits on Mar 18, 2013
  1. @texdc

    Add missing byValue argument

    texdc authored
  2. @texdc
Commits on Apr 26, 2013
  1. @texdc

    Adding documentation

    texdc authored
  2. @texdc

    Rebasing

    texdc authored
  3. @texdc
This page is out of date. Refresh to see the latest.
View
4 .gitignore
@@ -1,7 +1,9 @@
+.project
+*.prefs
.idea
vendor
composer.lock
composer.phar
phpunit.xml
phpmd.xml
-phpdox.xml
+phpdox.xml
View
29 docs/hydrator.md
@@ -380,6 +380,35 @@ class BlogPost
}
```
+It's also possible to use a nested fieldset for the User data. The hydrator will
+use the mapping data to determine the identifiers for the toOne relation and either
+attempt to find the existing record or instanciate a new target instance which will
+be hydrated before it is passed to the BlogPost entity.
+
+**NOTE** : you're not really allowing users to be added via a blog post, are you?
+
+```php
+use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
+
+$hydrator = new DoctrineHydrator($entityManager, 'Application\Entity\BlogPost');
+$blogPost = new BlogPost();
+
+$data = array(
+ 'title' => 'Art thou mad?',
+ 'user' => array(
+ 'id' => '',
+ 'username' => 'willshakes',
+ 'password' => '2BorN0t2B'
+ )
+);
+
+$blogPost = $hydrator->hydrate($data, $blogPost);
+
+echo $blogPost->getUser()->getUsername(); // prints willshakes
+echo $blogPost->getUser()->getPassword(); // prints 2BorN0t2B
+```
+
+
#### Example 3 : OneToMany association
View
14 src/DoctrineModule/Stdlib/Hydrator/DoctrineObject.php
@@ -337,6 +337,11 @@ protected function tryConvertArrayToObject($data, $object)
/**
* Handle ToOne associations
*
+ * When $value is an array but is not the $target's identifiers, $value is
+ * most likely an array of fieldset data. The identifiers will be determined
+ * and a target instance will be initialized and then hydrated. The hydrated
+ * target will be returned.
+ *
* @param string $target
* @param mixed $value
* @return object
@@ -347,6 +352,15 @@ protected function toOne($target, $value)
return $value;
}
+ $metadata = $this->objectManager->getClassMetadata($target);
+ if (is_array($value) && array_keys($value) != $metadata->getIdentifier()) {
+ // $value is most likely an array of fieldset data
+ $identifiers = array_intersect_key($value, array_flip($metadata->getIdentifier()));
+ $object = $this->find($identifiers, $target) ?: new $target;
+ $hydrator = new DoctrineObject($this->objectManager, $target, $this->byValue);
+ return $hydrator->hydrate($value, $object);
+ }
+
return $this->find($value, $target);
}
View
88 tests/DoctrineModuleTest/Stdlib/Hydrator/DoctrineObjectTest.php
@@ -186,6 +186,12 @@ public function configureObjectManagerForSimpleEntityWithDateTime()
$this
->metadata
->expects($this->any())
+ ->method('getIdentifier')
+ ->will($this->returnValue(array('id')));
+
+ $this
+ ->metadata
+ ->expects($this->any())
->method('getFieldNames')
->will($this->returnValue(array('id', 'date')));
@@ -193,7 +199,13 @@ public function configureObjectManagerForSimpleEntityWithDateTime()
->metadata
->expects($this->any())
->method('getTypeOfField')
- ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('date')))
+ ->with(
+ $this->logicalOr(
+ $this->equalTo('id'),
+ $this->equalTo('date'),
+ $this->equalTo('field')
+ )
+ )
->will(
$this->returnCallback(
function ($arg) {
@@ -201,6 +213,8 @@ function ($arg) {
return 'integer';
} elseif ($arg === 'date') {
return 'datetime';
+ } elseif ($arg === 'field') {
+ return 'string';
}
throw new \InvalidArgumentException();
@@ -251,6 +265,12 @@ public function configureObjectManagerForOneToOneEntity()
$this
->metadata
->expects($this->any())
+ ->method('getIdentifier')
+ ->will($this->returnValue(array('id')));
+
+ $this
+ ->metadata
+ ->expects($this->any())
->method('getAssociationNames')
->will($this->returnValue(array('toOne')));
@@ -312,6 +332,12 @@ function ($arg) {
->method('getReflectionClass')
->will($this->returnValue($refl));
+ $this
+ ->metadata
+ ->expects($this->any())
+ ->method('getIdentifier')
+ ->will($this->returnValue(array('id')));
+
$this->hydratorByValue = new DoctrineObjectHydrator(
$this->objectManager,
'DoctrineModuleTest\Stdlib\Hydrator\Asset\OneToOneEntity',
@@ -337,6 +363,12 @@ public function configureObjectManagerForOneToOneEntityNotNullable()
$this
->metadata
->expects($this->any())
+ ->method('getIdentifier')
+ ->will($this->returnValue(array('id')));
+
+ $this
+ ->metadata
+ ->expects($this->any())
->method('getAssociationNames')
->will($this->returnValue(array('toOne')));
@@ -344,7 +376,13 @@ public function configureObjectManagerForOneToOneEntityNotNullable()
->metadata
->expects($this->any())
->method('getTypeOfField')
- ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('toOne')))
+ ->with(
+ $this->logicalOr(
+ $this->equalTo('id'),
+ $this->equalTo('toOne'),
+ $this->equalTo('field')
+ )
+ )
->will(
$this->returnCallback(
function ($arg) {
@@ -352,6 +390,8 @@ function ($arg) {
return 'integer';
} elseif ($arg === 'toOne') {
return 'DoctrineModuleTest\Stdlib\Hydrator\Asset\SimpleEntity';
+ } elseif ($arg === 'field') {
+ return 'string';
}
throw new \InvalidArgumentException();
@@ -363,11 +403,17 @@ function ($arg) {
->metadata
->expects($this->any())
->method('hasAssociation')
- ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('toOne')))
+ ->with(
+ $this->logicalOr(
+ $this->equalTo('id'),
+ $this->equalTo('toOne'),
+ $this->equalTo('field')
+ )
+ )
->will(
$this->returnCallback(
function ($arg) {
- if ($arg === 'id') {
+ if ($arg === 'id' || $arg === 'field') {
return false;
} elseif ($arg === 'toOne') {
return true;
@@ -398,6 +444,12 @@ function ($arg) {
->method('getReflectionClass')
->will($this->returnValue($refl));
+ $this
+ ->metadata
+ ->expects($this->any())
+ ->method('getIdentifier')
+ ->will($this->returnValue(array('id')));
+
$this->hydratorByValue = new DoctrineObjectHydrator(
$this->objectManager,
'DoctrineModuleTest\Stdlib\Hydrator\Asset\OneToOneEntityNotNullable',
@@ -759,6 +811,34 @@ public function testHydrateOneToOneAssociationByValueUsingIdentifierArrayForRela
$this->assertSame($entityInDatabaseWithIdOfOne, $entity->getToOne(false));
}
+ public function testHydrateOneToOneAssociationByValueUsingFullArrayForRelation()
+ {
+ // When using hydration by value, it will use the public API of the entity to set values (setters)
+ $entity = new Asset\OneToOneEntityNotNullable;
+ $this->configureObjectManagerForOneToOneEntityNotNullable();
+
+ // Use entity of id 1 as relation
+ $data = array('toOne' => array('id' => 1, 'field' => 'foo'));
+
+ $entityInDatabaseWithIdOfOne = new Asset\SimpleEntity();
+ $entityInDatabaseWithIdOfOne->setId(1);
+ $entityInDatabaseWithIdOfOne->setField('bar', false);
+
+ $this
+ ->objectManager
+ ->expects($this->once())
+ ->method('find')
+ ->with('DoctrineModuleTest\Stdlib\Hydrator\Asset\SimpleEntity', array('id' => 1))
+ ->will($this->returnValue($entityInDatabaseWithIdOfOne));
+
+ $entity = $this->hydratorByValue->hydrate($data, $entity);
+
+ $this->assertInstanceOf('DoctrineModuleTest\Stdlib\Hydrator\Asset\OneToOneEntityNotNullable', $entity);
+ $this->assertInstanceOf('DoctrineModuleTest\Stdlib\Hydrator\Asset\SimpleEntity', $entity->getToOne(false));
+ $this->assertSame($entityInDatabaseWithIdOfOne, $entity->getToOne(false));
+ $this->assertEquals('From getter: Modified from setToOne setter', $entityInDatabaseWithIdOfOne->getField());
+ }
+
public function testHydrateOneToOneAssociationByReferenceUsingIdentifierArrayForRelation()
{
// When using hydration by reference, it won't use the public API of the entity to set values (setters)
Something went wrong with that request. Please try again.