在Doctrine中跨集合移动实体



这个问题与我这里的另一个问题有点相关ArrayCollection (Doctrine)包含函数返回不正确的结果,所以如果有人想要更多关于我的问题的信息,它在那里,虽然这不是严格相同的问题。

现在,到这一点,我有一个FileSystemFolder模型一个文件夹,和一个FileProxy模型一个文件,FileSystemFolder包含一个FileProxy的ArrayCollection,我也有一个FileManager,执行移动操作,你会期望在任何文件系统上都有。这个移动操作需要两个文件系统文件夹和一个文件代理,从一个文件系统文件夹中删除这个文件代理,并将其添加到另一个文件系统文件夹中。

下面是这个函数:

public function moveFileProxy(FileSystemFolder $from, FileSystemFolder $to, FileProxy $proxy, $force = false)
{
    if (!$this->checkFolder($from))
    {
        return array('type' => 'error', 'message' => 'Cannot move from this folder.');
    }
    if (!$force)
    {
        if (!$this->checkFolder($to))
        {
            return array('type' => 'error', 'message' => 'Cannot move to this folder.');
        }
    }
    /*$return = "";
    foreach($from->getFiles() as $file)
    {
        $return .= $file->getFilename() . " --- ";
    }
    if(!$from->getFiles()->contains($proxy))
    {
        return array('type' => 'error', 'message' => 'Folder '.$from->getName().' does not contain '.$proxy->getFilename(). ' All files from this folder '. $return);
    }
    if($to->getFiles()->contains($proxy))
    {
        return array('type' => 'error', 'message' => 'Folder '.$to->getName().' already contains '.$proxy->getFilename());
    }*/
    $from->removeFile($proxy);
    $to->addFile($proxy);
    return array('type' => 'pass', 'message' => 'Operation Successful.');
}

注释掉的代码属于另一个问题。检查不重要。

为了回答这个问题,我将从另一个问题中抄一条信息,因为它很重要,在这里:

/**
 * @ORMManyToMany(targetEntity="FileProxy", fetch="EXTRA_LAZY")
 * @ORMJoinTable(name="file_system_folders_files",
 *      joinColumns={@ORMJoinColumn(name="file_system_folder_id",     referencedColumnName="id")},
 *      inverseJoinColumns={@ORMJoinColumn(name="proxy_id",     referencedColumnName="id", unique=true)})
 */
protected $files;

:

/**
 * Add proxy
 * 
 * @param FileProxy $proxy
 * @return FileSystemFolder
 */
public function addFile(FileProxy $proxy)
{
    if(!$this->getFiles()->contains($proxy))
    {
        $this->getFiles()->add($proxy);
    }
    return $this;
}
/**
 * Remove proxy
 *
 * @param FileProxy $proxy
 * @return FileSystemFolder
 */
public function removeFile(FileProxy $proxy)
{
    if($this->getFiles()->contains($proxy))
    {            
        $this->getFiles()->removeElement($proxy);
    }
    return $this;
}

现在,这些函数是非常直接的,它们真的不做任何花哨的事情,就像它们的名字告诉我们的那样,有趣的是,moveFileProxy函数工作得非常好(我坚持两个文件夹的这个函数,我认为这是一个很好的做法)。

问题是:这个函数实际上应该工作吗?正如你所看到的,$files变量是一个ArrayCollection,它没有级联持久化,它没有级联任何东西,但是这个函数仍然有效。

下面是显示整个过程的一段代码:

$result = $fm->moveFileProxy($origin, $destination, $upload);
    if($result['type'] === 'error')
    {
        return JsonResponse::create($result);
    }
    $em = $this->getDoctrine()->getManager();
    $em->persist($origin);
    $em->persist($destination);
    $em->flush();

但是它在大多数情况下工作,大多数情况下它不会抛出错误,但有时,在一些奇怪的情况下,它会抛出"重复条目异常",这也很奇怪,因为这毕竟是一个移动操作。

如果你知道任何关于这个问题,请帮助我,#symfony和#doctrine IRCs在帮助方面真的很糟糕。

谢谢。

看起来,我发现了这个问题的答案
(完全是偶然的),但我不完全确定,我不认为它记录在Doctrine文档中。它可能隐藏在代码的某个地方,我可能稍后会查找它来证明这个理论。

我的理论是:

单向多对多关联创建了一个额外的表,因此该关联由3个表组成,没有实际的多对多关联,这2个表显然是您用来形成关联的表,但第三个表很重要。

第三个表是Doctrine当场创建的,尽管我们用@JoinColumn指定了列的属性,但我认为Doctrine实际上会进一步修改它们以实现级联持久化,因为否则就没有实际意义了。

我也很确定,它实际上是级联的,但就像我说的,这只是一个理论。

最新更新