我使用merge()
没有任何运气。我正在做几乎完全记录的事情:
/* @var $detachedDocument MyDocumentClass */
$detachedDocument = unserialize($serializedDocument);
$document = $dm->merge($detachedDocument);
$document->setLastUpdated(new 'MongoDate());
$dm->persist($document);
但这种变化永远不会持续下去。我必须这样做:
$dm->createQueryBuilder('MyDocumentClass')
->findAndUpdate()
->field('lastUpdated')->set(new 'MongoDate())
->getQuery()
->execute();
merge()
似乎很简单,所以我很困惑为什么它不能像我认为的那样工作。
在您的第一个代码示例中,merge()
后跟 persist()
是多余的,并且您省略了 flush()
,这是实际写入数据库的唯一操作(除非您手动执行查询,如在第二个示例中所做的那样)。如果你在 UnitOfWork::doMerge()
中浏览代码,你会看到它将保留对象(如果它没有 ID)或按其 ID 获取文档。最终结果是merge()
返回一个托管文档。持久化可确保在调用文档后对其进行管理(它本身不返回任何内容)。如果您戳UnitOfWork::doPersist()
,您会发现将托管对象传递给该方法实际上是一个 NOOP。
尝试将persist()
替换为 flush()
。请注意,如有必要,您可以刷新单个文档,但默认情况下$dm->flush()
处理所有托管对象。
如果这仍然没有帮助,我会确认 lastUpdated
字段已在 ODM 中正确映射。您可以检查$dm->getClassMetadata('MyDocumentClass')
的输出进行确认。如果它不是映射字段,UnitOfWork 将检测到文档中没有更改,并且不会有任何要刷新的内容。
顺便说一句:在第二个代码示例中,您在没有任何搜索条件的情况下执行findAndUpdate()
(仅指定set()
)。通常,您将修改与类似 equals()
(在您的情况下可能是 ID)之类的内容配对,以确保以原子方式修改并返回单个文档。