I have a document that has a document embedded. When I create an object for the first time everything works fine, but when I try to update a document, the embedded document does not get updated.
/** @MongoDB\Document */
class DocumentA
{
/** @MongoDB\EmbedOne(targetDocument="DocumentB") **/
protected $docB;
/** @MongoDB\String */
protected $valueA;
}
/** @MongoDB\EmbeddedDocument */
class DocumentB
{
/** @MongoDB\String */
protected $valueB;
}
In my application I query for a document, update the values and persist them to the data store.
// Variant A – Does not work
$document = ... // find from data store
$document->setValueA('Hello World');
$document->getDocB()->setValueB('foo baz');
$om->persist($document);
$om->flush();
If I do not update the embedded document, but set a new one everything works fine:
// Variant B - Does work
$document = ... // find from data store
$document->setValueB('Hello World 2');
$document->setDocB(new DocumentB());
$document->getDocB()->setValueB('foo baz 2');
$om->persist($document);
$om->flush();
As I said, Variant B works fine. However, in my application the documents are more complex and it would be impractical for me to create a new object for the embedded document every time I have to update it. Is there a method to tell Doctrine ODM to look at the values of an embedded document to decide if it should be updated?
Accessing embedded/nested documents – In MongoDB, you can access the fields of nested/embedded documents of the collection using dot notation and when you are using dot notation, then the field and the nested field must be inside the quotation marks.
MongoDB provides you a cool feature which is known as Embedded or Nested Document. Embedded document or nested documents are those types of documents which contain a document inside another document.
I faced exactly the same issue. It turns out the UnitOfWork seems to fail in computing the changesets of documents with other documents embedded, though I have not been able to figure out why... As a result, when when i compare the actual value and the original one, unit of work shows the same value for both. Speaking with your Variant A, when you
$document->getDocB()->setValueB('foo baz');
Unit of work shows "foo baz" for both the old and the new value and will not recognize it as a a change and will therefor not update it.
Anyway, this leeds to a workaround:
$document = ... // find from data store
$document->setValueA('Hello World');
$docB = $document->getDocB();
$docB->setValueB('foo baz');
$om->detach($docB);
$om->persist($document);
$om->flush();
This makes the unit of work recognize the docB of $document as a newly set document and will flush it as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With