OneToMany的Doctrine Cascade选项

can*_*era 39 cascade doctrine-orm

我很难理解Doctrine手册对级联操作的解释,需要有人帮助我理解简单的ManyToOne关系中的选项.

在我的应用程序中,我有一个名为Article的表/实体,它有一个外键字段,引用名为Topic的表/实体中的'id'字段.

当我创建新文章时,我从下拉菜单中选择主题.这会在Article表的'topic_id'外键字段中插入一个整数.

我在Article实体中设置了$ topic关联,如下所示:

/**
 * @ManyToOne(targetEntity="Topic")
 * @JoinColumn(name="topic_id", referencedColumnName="id", nullable=false)
 */
private $topic;
Run Code Online (Sandbox Code Playgroud)

主题实体没有关于Article实体的任何往复注释.当删除引用主题的文章时,主题不关心什么文章引用它们,并且不需要在主题中发生任何事情.

因为我没有在Article实体中指定级联操作,所以当我尝试创建新文章时,Doctrine会抛出错误:"通过未配置为级联持久操作的关系找到新实体.明确地保留新实体或者在关系上配置级联持久化操作."

所以我知道我需要选择一个级联操作来包含在Article实体中,但是我怎么知道在这种情况下选择哪个操作呢?

从阅读Doctrine手册开始,"分离"听起来就像是正确的选择.但是在这里这里研究其他人的类似问题让我觉得我想用"坚持"代替.

任何人都可以帮助我理解"持久","删除","合并"和"分离"是否意味着简单的ManyToOne关系,就像我所描述的那样?

Ser*_*nko 29

在Doctrine2文档" 9.6.传递持久性/级联操作 "中,很少有关于如何配置实体的示例,以便当您持久保存$ article时,$ topic也将保持不变.在你的情况下,我建议为Topic实体注释:

/**
 * @OneToMany(targetEntity="Article", mappedBy="topic", cascade={"persist", "remove"})
 */
 private $articles;  
Run Code Online (Sandbox Code Playgroud)

此解决方案的缺点是您必须将$ articles集合包含在Topic实体中,但是您可以将其保留为私有而不使用getter/setter.

正如@ kurt-krueckeberg所提到的,你必须在创建新文章时传递真正的主题实体,即:

$topic = $em->getRepository('Entity\Topic')->find($id);
$article = new Article($topic);
$em->persist($article);
$em->flush();

// perhaps, in this case you don't even need to configure cascade operations
Run Code Online (Sandbox Code Playgroud)

祝好运!