我有一个文档,该文档具有另一个文档的 ReferenceMany 属性。引用设置正常,数据从查询返回正常,但 arraycollection 中的每个文档都作为代理返回。在这个网站上,我看到有人提到我应该添加->prime(true)
以返回实际引用的文档。
当返回文档的 ArrayCollection 时,我正在运行一个已提交给服务器的 id 循环,以将它们从引用的集合中删除。该removeElement
方法不起作用 b/c 返回的文档是代理,我正在比较实际文档与那些代理。所以基本上我正在尝试:
- 查找单个文档
- 强制
ReferenceMany
属性中的所有文档为实际文档而不是代理文档 - 循环遍历我的 id 数组并加载每个文档
- 将文档发送到 removeElement 方法
在下面的第一个getSingleResult
查询方法中,我收到一个错误cannot modify cursor after beginning iteration
。我在这个网站上看到一个帖子提到你应该初始化结果,以便获取实际文档而不是代理,在他的示例中,他使用了getSingleResult
.
$q = $this->dm->createQueryBuilder('\FH\Document\Person')->field('target')->prime(true)->field('id')->equals($data->p_id);
$person = $q->getQuery()->getSingleResult();
foreach($data->loc_id as $loc) {
$location = $this->dm->createQueryBuilder('\FH\Document\Location')->field('id')->equals(new \MongoId($loc))->getQuery()->getSingleResult();
$person->removeTarget($location);
}
....
....
....
public function removeTarget($document)
{
$this->target->removeElement($document);
return $this;
}
如果我->prime(true)
从第一个查询中删除,它不会引发错误,但它实际上并没有删除任何元素,即使我在方法上设置断点,比较两个文档,并且数据完全相同,除了$this->target
它们是Location
代理文档,加载的是一个实际的Location
文档。
我可以以某种方式启动单个结果,以便我可以ArrayCollection
正确使用这些方法,还是我需要做一些 for 循环并比较 id?
更新
所以这是一个显示我遇到的问题的更新。虽然下面的解决方案只使用 MongoId(s),但当我提交一个实际的 Document 类时,它从未真正删除该文档。ArrayCollection 作为 PersistentCollection 从 Doctrine 中返回。中的每个元素$this->coll
都属于此 Document 类型:
DocumentProxy\__CG__\FH\Document\Location
实际的文件是这样的:
FH\Document\Location
该removeElement
方法执行这样的array_search:
public function removeElement($element)
{
$key = array_search($element, $this->_elements, true);
if ($key !== false) {
unset($this->_elements[$key]);
return true;
}
return false;
}
所以因为对象类型并不完全相同,即使代理对象应该是从我创建的实际 Document 继承的,也$key
总是返回 0(false),因此不会删除该元素。两个文档之间的所有内容都完全相同,除了对象类型。
就像我说的,我想我可以通过 MongoId 来做到这一点,但是为什么不能通过提交整个对象来工作呢?