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

@iampersistent

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

@kriswallsmith
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;
@iampersistent

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.

@kriswallsmith
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') {
@jwage 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') {
@jwage 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') {
@jwage 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
@jwage
Owner

:+1:

@iampersistent

Fixed. @jwage, thanks for pointing those out.

@jwage jwage merged commit d36765c into from
@kriswallsmith
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?

@kriswallsmith
Collaborator

From the trace:

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

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

@iampersistent

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.

@tecbot

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

@iampersistent

@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

@tecbot

@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.

@kriswallsmith
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.

@kriswallsmith kriswallsmith referenced this pull request from a commit
@kriswallsmith 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. @iampersistent
Commits on Nov 16, 2011
  1. @iampersistent
Commits on Nov 24, 2011
  1. @iampersistent

    Fix comparison

    iampersistent authored
  2. @iampersistent

    update comparisons

    iampersistent authored
This page is out of date. Refresh to see the latest.
View
9 lib/Doctrine/ODM/MongoDB/PersistentCollection.php
@@ -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();
}
View
14 lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php
@@ -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.