为什么我需要在 remove() 之后和 persist() 之前刷新()



我有以下代码:

//Delete old existing file(s)
$files = $record->getFiles();
foreach ($files as $file) {
   $em->remove($file);
}
$em->flush();
$link = $record->getLink() ? $record->getLink() : new Link();
$link->setRecord($record);
$link->setUrl($metaData['location']);
$em->persist($link);
$em->flush();

我需要调用第一个flush()否则$file实体不会被删除。为什么不只使用第二个flush()来删除它们?

作为参考,这里是Record的关系定义:

/**
 * @var AppBundleEntityLink
 *
 * @ORMOneToOne(targetEntity="AppBundleEntityLink", cascade={"persist"}, mappedBy="record")
 */
private $link;
/**
 * @var AppBundleEntityFile
 *
 * @ORMOneToMany(targetEntity="AppBundleEntityFile", cascade={"persist"}, mappedBy="record")
 */
private $files;

此外,使用单个 flush(( 的这段代码工作正常(它删除的是一对一实体而不是一对一实体(:

 //Delete old existing link
 $link = $record->getLink();
 if ($link) {
      $em->remove($link);
 }
 $file = $record->getFile() ? $record->getFile() : new File();
 $file->setRecord($record);
 $em->persist($file);
 $em->flush();

cascade 参数有一个选项:"删除"、"保留"、"刷新"、"合并"和"分离"。

将它们视为标志,以便您可以编写:

cascade={"persist","remove"}

甚至:

cascade={"all"}

也许这有帮助...

我找到了两种使代码工作的方法,它们采用两种不同的方法:

第一种情况:不要在实体中设置任何级联逻辑,而是手动处理所有操作。

记录实体

/**
 * @var AppBundleEntityLink
 *
 * @ORMOneToOne(targetEntity="AppBundleEntityLink", mappedBy="record")
 */
private $link;
/**
 * @var AppBundleEntityFile
 *
 * ORMOneToMany(targetEntity="AppBundleEntityFile", mappedBy="record")
 */
private $files;

控制器

//Delete old existing file(s)
$files = $record->getFiles();
foreach ($files as $file) {
    $fileService->deleteFile($file);
    //Remove the *owning* entity of the relationship
    $em->remove($file);
}
$em->flush();
$em->clear();
//We need to call clear() to remove all existing references of files 
//from the $record entity. Get the record again after this.
$record = $this->getRecordRepository()->findActive($id);
$link = $record->getLink() ? $record->getLink() : new Link();
$link->setRecord($record);
$link->setUrl($metaData['location']);
$em->persist($link);
$record->setType(Record::TYPE_LINK);
$em->flush();

第二种情况:从$record的角度处理所有数据库操作,让cascadeorphanRemoval完成其余的工作

记录实体

/**
 * @var AppBundleEntityLink
 *
 * @ORMOneToOne(targetEntity="AppBundleEntityLink", cascade={"persist", "remove"}, mappedBy="record", orphanRemoval=true)
 */
private $link;
/**
 * @var AppBundleEntityFile
 *
 * @ORMOneToMany(targetEntity="AppBundleEntityFile", cascade={"persist", "remove"}, mappedBy="record", orphanRemoval=true)
 */
private $files;

控制器

//Delete old existing file(s)
$files = $record->getFiles();
foreach ($files as $file) {
    $fileService->deleteFile($file);
    $record->removeFile($file);
}
$link = $record->getLink() ? $record->getLink() : new Link();
$link->setRecord($record);
$link->setUrl($metaData['location']);
$em->persist($link);
$record->setType(Record::TYPE_LINK);
$em->flush();

我个人倾向于第二种方法,它需要更少的PHP代码更具可读性。

我将保留此答案以开放任何评论/提示,并在本周关闭它。

相关内容

  • 没有找到相关文章

最新更新