第二种情况:从
我有以下代码:
//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
的角度处理所有数据库操作,让cascade
和orphanRemoval
完成其余的工作
记录实体
/**
* @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代码更具可读性。
我将保留此答案以开放任何评论/提示,并在本周关闭它。