Skip to content
This repository

[bug fix] Load keys on set strategy on embed-many and reference-many #194

Merged
merged 4 commits into from over 2 years ago

4 participants

Richard Shank Kris Wallsmith Jonathan H. Wage Thomas Adam
Richard Shank

Currently, when loading "many" data using the set strategy, the key is lost when the data is loaded. This code corrects that problem.

Kris Wallsmith
Collaborator

Does this patch enable this sort of thing?

<?php

class Person
{
  /** @ReferenceMany */
  public $relations = array();
}

$me = new Person();
$mom = new Person();
$me->relations['mother'] = $mom;
Richard Shank

Yes it does. The persisting side of it was patched a couple of months ago , sadly I'm just now getting to using the loading side of it.

It doesn't do anything with the inverse side mapping or repository method mapping, it just didn't make sense to me in this context.

Kris Wallsmith
Collaborator

:+1:

lib/Doctrine/ODM/MongoDB/PersistentCollection.php
@@ -139,8 +139,12 @@ class PersistentCollection implements BaseCollection
139 139
             $this->takeSnapshot();
140 140
             // Reattach NEW objects added through add(), if any.
141 141
             if (isset($newObjects)) {
142  
-                foreach ($newObjects as $obj) {
143  
-                    $this->coll->add($obj);
  142
+                foreach ($newObjects as $key => $obj) {
  143
+                    if ($this->mapping['strategy'] == 'set') {
1
Jonathan H. Wage Owner
jwage added a note November 24, 2011

Need === here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php
@@ -513,7 +513,11 @@ class DocumentPersister
513 513
                 $data = $this->hydratorFactory->hydrate($embeddedDocumentObject, $embeddedDocument);
514 514
                 $this->uow->registerManaged($embeddedDocumentObject, null, $data);
515 515
                 $this->uow->setParentAssociation($embeddedDocumentObject, $mapping, $owner, $mapping['name'].'.'.$key);
516  
-                $collection->add($embeddedDocumentObject);
  516
+                if ($mapping['strategy'] == 'set') {
1
Jonathan H. Wage Owner
jwage added a note November 24, 2011

Need === here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php
((6 lines not shown))
527 531
             $className = $this->dm->getClassNameFromDiscriminatorValue($mapping, $reference);
528 532
             $mongoId = $reference[$cmd . 'id'];
529 533
             $id = (string) $mongoId;
530 534
             $reference = $this->dm->getReference($className, $id);
531  
-            $collection->add($reference);
  535
+            if ($mapping['strategy'] == 'set') {
1
Jonathan H. Wage Owner
jwage added a note November 24, 2011

Need === here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Jonathan H. Wage
Owner

:+1:

Richard Shank

Fixed. @jwage, thanks for pointing those out.

Jonathan H. Wage jwage merged commit d36765c into from December 02, 2011
Jonathan H. Wage jwage closed this December 02, 2011
Kris Wallsmith
Collaborator

I am getting a "Cannot apply $pull/$pullAll modifier to non-array" error when I remove an embedded document from an @EmbedMany(strategy="set") collection and flush. Any ideas?

Kris Wallsmith
Collaborator

From the trace:

MongoCollection->update(array('_id' => object(MongoId)), array('$pull' => array('socialProfiles' => null)), array('safe' => true))
Thomas Adam

can you show your content from mongodb for this field, pls?

I think after this pull request the content shows like this:

{
   "socialProfiles": {
   "0":  {
       "name": "foo",
    },
   "1":  {
       "name": "bar",
    }
  }
}

and this is no array, it is a embedded document for mongodb.
Expected:

{
   "socialProfiles": [
    {
       "name": "foo",
    },
    {
       "name": "bar",
    }
  ],
}

So the pull requests brokes the pull operation for the set strategy

Richard Shank

I was getting that same error when I first started work on the first PR for this I can't remember off hand if handling the delete goes through there also or somewhere else. That's where I'd start looking.

Thomas Adam

We need to use the unset operation if we should delete a entry for the 'set' strategy

Richard Shank

@kriswallsmith, now that I actually look at the code, the problem must be with line https://github.com/doctrine/mongodb-odm/blob/master/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php#L141 we probably need to do a check to see if we are using the set strategy and if we are, then don't execute line 141. Just a guess. I might have some time to look at it on Sunday

Thomas Adam

@IamPersistent I think you're right with your guess, because it is a normal object for mongodb and a $unset query is enough to remove a field.

Kris Wallsmith
Collaborator

The $pull hack is necessary after an $unset query such as...

db.foo.update({ _id: id }, { $unset: { "favoriteColors.2": true }})

...but not after...

db.foo.update({ _id: id }, { $unset: { "socialIdentities.facebook": true }})

I think @IamPersistent is correct that we tell the difference by checking the strategy. I'll submit a PR.

Kris Wallsmith kriswallsmith referenced this pull request from a commit December 03, 2011
Kris Wallsmith added conditional around collection delete hack
the extra $pull query is not necessary when using the set strategy (see discussion on #194)
111de2c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
9  lib/Doctrine/ODM/MongoDB/PersistentCollection.php
@@ -139,8 +139,12 @@ public function initialize()
139 139
             $this->takeSnapshot();
140 140
             // Reattach NEW objects added through add(), if any.
141 141
             if (isset($newObjects)) {
142  
-                foreach ($newObjects as $obj) {
143  
-                    $this->coll->add($obj);
  142
+                foreach ($newObjects as $key => $obj) {
  143
+                    if ($this->mapping['strategy'] === 'set') {
  144
+                        $this->coll->set($key, $obj);
  145
+                    } else {
  146
+                        $this->coll->add($obj);
  147
+                    }
144 148
                 }
145 149
                 $this->isDirty = true;
146 150
             }
@@ -419,7 +423,6 @@ public function count()
419 423
      */
420 424
     public function set($key, $value)
421 425
     {
422  
-        $this->initialize();
423 426
         $this->coll->set($key, $value);
424 427
         $this->changed();
425 428
     }
14  lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php
@@ -513,7 +513,11 @@ private function loadEmbedManyCollection(PersistentCollection $collection)
513 513
                 $data = $this->hydratorFactory->hydrate($embeddedDocumentObject, $embeddedDocument);
514 514
                 $this->uow->registerManaged($embeddedDocumentObject, null, $data);
515 515
                 $this->uow->setParentAssociation($embeddedDocumentObject, $mapping, $owner, $mapping['name'].'.'.$key);
516  
-                $collection->add($embeddedDocumentObject);
  516
+                if ($mapping['strategy'] === 'set') {
  517
+                    $collection->set($key, $embeddedDocumentObject);
  518
+                } else {
  519
+                    $collection->add($embeddedDocumentObject);
  520
+                }
517 521
             }
518 522
         }
519 523
     }
@@ -523,12 +527,16 @@ private function loadReferenceManyCollectionOwningSide(PersistentCollection $col
523 527
         $mapping = $collection->getMapping();
524 528
         $cmd = $this->cmd;
525 529
         $groupedIds = array();
526  
-        foreach ($collection->getMongoData() as $reference) {
  530
+        foreach ($collection->getMongoData() as $key => $reference) {
527 531
             $className = $this->dm->getClassNameFromDiscriminatorValue($mapping, $reference);
528 532
             $mongoId = $reference[$cmd . 'id'];
529 533
             $id = (string) $mongoId;
530 534
             $reference = $this->dm->getReference($className, $id);
531  
-            $collection->add($reference);
  535
+            if ($mapping['strategy'] === 'set') {
  536
+                $collection->set($key, $reference);
  537
+            } else {
  538
+                $collection->add($reference);
  539
+            }
532 540
             if ($reference instanceof Proxy && ! $reference->__isInitialized__) {
533 541
                 if ( ! isset($groupedIds[$className])) {
534 542
                     $groupedIds[$className] = array();
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.