Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

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

Merged
merged 4 commits into from

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
$this->takeSnapshot();
// Reattach NEW objects added through add(), if any.
if (isset($newObjects)) {
- foreach ($newObjects as $obj) {
- $this->coll->add($obj);
+ foreach ($newObjects as $key => $obj) {
+ if ($this->mapping['strategy'] == 'set') {
Jonathan H. Wage Owner
jwage added a note

Need === here.

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

Need === here.

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

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
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
Kris Wallsmith kriswallsmith 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
Commits on Nov 15, 2011
  1. Richard Shank
Commits on Nov 16, 2011
  1. Richard Shank
Commits on Nov 24, 2011
  1. Richard Shank

    Fix comparison

    iampersistent authored
  2. Richard Shank

    update comparisons

    iampersistent authored
This page is out of date. Refresh to see the latest.
9 lib/Doctrine/ODM/MongoDB/PersistentCollection.php
View
@@ -139,8 +139,12 @@ public function initialize()
$this->takeSnapshot();
// Reattach NEW objects added through add(), if any.
if (isset($newObjects)) {
- foreach ($newObjects as $obj) {
- $this->coll->add($obj);
+ foreach ($newObjects as $key => $obj) {
+ if ($this->mapping['strategy'] === 'set') {
+ $this->coll->set($key, $obj);
+ } else {
+ $this->coll->add($obj);
+ }
}
$this->isDirty = true;
}
@@ -419,7 +423,6 @@ public function count()
*/
public function set($key, $value)
{
- $this->initialize();
$this->coll->set($key, $value);
$this->changed();
}
14 lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php
View
@@ -513,7 +513,11 @@ private function loadEmbedManyCollection(PersistentCollection $collection)
$data = $this->hydratorFactory->hydrate($embeddedDocumentObject, $embeddedDocument);
$this->uow->registerManaged($embeddedDocumentObject, null, $data);
$this->uow->setParentAssociation($embeddedDocumentObject, $mapping, $owner, $mapping['name'].'.'.$key);
- $collection->add($embeddedDocumentObject);
+ if ($mapping['strategy'] === 'set') {
+ $collection->set($key, $embeddedDocumentObject);
+ } else {
+ $collection->add($embeddedDocumentObject);
+ }
}
}
}
@@ -523,12 +527,16 @@ private function loadReferenceManyCollectionOwningSide(PersistentCollection $col
$mapping = $collection->getMapping();
$cmd = $this->cmd;
$groupedIds = array();
- foreach ($collection->getMongoData() as $reference) {
+ foreach ($collection->getMongoData() as $key => $reference) {
$className = $this->dm->getClassNameFromDiscriminatorValue($mapping, $reference);
$mongoId = $reference[$cmd . 'id'];
$id = (string) $mongoId;
$reference = $this->dm->getReference($className, $id);
- $collection->add($reference);
+ if ($mapping['strategy'] === 'set') {
+ $collection->set($key, $reference);
+ } else {
+ $collection->add($reference);
+ }
if ($reference instanceof Proxy && ! $reference->__isInitialized__) {
if ( ! isset($groupedIds[$className])) {
$groupedIds[$className] = array();
Something went wrong with that request. Please try again.