OneToMany的学说Cascade选项
我很难理解Doctrine手册中有关级联操作的解释 ,需要有人帮助我理解简单的ManyToOne关系的选项。
在我的应用程序中,我有一个名为Article的表/实体,它有一个外键字段,引用名为Topic的表/实体中的“id”字段。
当我创build一个新的文章,我从下拉菜单中select主题。 这会在文章表中的“topic_id”外键字段中插入一个整数。
我在Article实体中设置了$ topic关联,如下所示:
/** * @ManyToOne(targetEntity="Topic") * @JoinColumn(name="topic_id", referencedColumnName="id", nullable=false) */ private $topic;
Topic主题实体没有任何关于Article实体的相互注释。 主题不关心什么文章引用它们,当引用该主题的文章被删除时什么都不需要发生在主题上。
因为我没有在Article实体中指定级联操作,所以当我尝试创build一个新的Article时,Doctrine会抛出一个错误:“通过未configuration为级联持久化操作的关系find新的实体。显式地坚持新的实体或者在关系上configuration级联持久化操作。“
所以我知道我需要select一个级联操作来包含在Article实体中,但是我怎么知道在这种情况下select哪个操作呢?
从阅读教义手册,“分离”听起来像是正确的select。 但是在这里和这里研究别人的类似问题让我觉得我想用“坚持”来代替。
任何人都可以帮助我理解什么“坚持”,“删除”,“合并”和“分离”意味着就像我所描述的一个简单的ManyToOne关系?
在Doctrine2文档“ 9.6.Transitive持久性/级联操作 ”中,有几个例子说明你应该如何configuration你的实体,这样当你坚持$ article时,$ topic也将被持久化。 在你的情况下,我会build议这个注释主题实体:
/** * @OneToMany(targetEntity="Article", mappedBy="topic", cascade={"persist", "remove"}) */ private $articles;
这个解决scheme的缺点是你必须包含$ articles集合到Topic实体,但是你可以不用getter / setter保密。
正如@ kurt-krueckeberg所提到的,创build新文章时必须传递实际的Topic实体,即:
$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
祝你好运!
如果你有一个@OneToMany单向关联,就像Doctrine Reference的6.10节所描述的那样,那么很可能你在调用flush之前忘记了坚持这个主题。 不要在文章中设置topic_id主键。 而是设置Topic实例。
例如,给定Article和Topic这样的实体:
<?php namespace Entities; /** @Entity @Table(name="articles") */ class Article { /** * @Id * @Column(type="integer", name="article_id") * @GeneratedValue */ protected $id; /** * @Column(type="text") */ protected $text; /** * @ManyToOne(targetEntity="Topic", inversedBy="articles") * @JoinColumn(name="topic_id", referencedColumnName="topic_id") */ protected $topic; public function __construct($text=null) { if (!is_null($text)) { $this->text = $text; } } public function setArticle($text) { $this->text = $text; } public function setTopic(Topic $t) { $this->topic = $t; } } <?php namespace Entities; /** @Entity @Table(name="topics") */ class Topic { /** * @Id * @Column(type="integer", name="topic_id") * @GeneratedValue */ protected $id; public function __construct() {} public function getId() {return $this->id;} }
在生成模式之后:
# doctrine orm:schema-tool:create
你的代码坚持这些实体将看起来像这样的事情
//configuration omitted.. $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config); $topic = new Entities\Topic(); $article1 = new Entities\Article("article 1"); $article2 = new Entities\Article("article 2"); $article1->setTopic($topic); $article2->setTopic($topic); $em->persist($article1); $em->persist($article2); $em->persist($topic); try { $em->flush(); } catch(Exception $e) { $msg= $e->getMessage(); echo $msg . "<br />\n"; } return;
我希望这有帮助。