持久化@OneToMany字段时自动传播身份

时间:2014-12-28 08:00:23

标签: php symfony doctrine-orm one-to-many

我正在开发twig小提琴,js / sql / php-fiddle相当于Twig language。我们可以添加几个模板来渲染结果,我有以下实体:

class Fiddle
{

    /**
     * @var ArrayCollection[FiddleTemplate]
     *
     * @ORM\OneToMany(targetEntity="FiddleTemplate", mappedBy="fiddle", cascade={"all"}, orphanRemoval=true)
     */
    protected $templates;

    // ...

}

class FiddleTemplate
{

    /**
     * @var Fiddle
     *
     * @ORM\ManyToOne(targetEntity="Fiddle", inversedBy="templates")
     * @ORM\JoinColumn(name="fiddle_id", referencedColumnName="id", onDelete="cascade")
     * @ORM\Id
     */
    protected $fiddle;

    /**
     * @var string
     *
     * @ORM\Column(name="filename", type="string", length=64)
     * @ORM\Id
     */
    protected $filename = 'main.twig';

    // ...
}

您可以想象,我可以在UI中添加/删除模板。

Fiddle的id是Fiddle实体的一部分,所以如果我想第一次坚持模板,我首先需要坚持小提琴。我是使用Doctrine事件的主持人(如果感兴趣的话,请参阅rev历史)。但是,如果我尝试将模板添加到已存在的小提琴并保存,我会提出以下异常:

  

Fuz \ AppBundle \ Entity \ FiddleTemplate类型的实体缺少一个   为“小提琴”分配了ID。标识符生成策略   此实体需要先填充ID字段   调用EntityManager#persist()。如果要自动生成   您需要调整元数据映射   相应

听起来足够逻辑,因为我需要在持久化之前将Fiddle的实例传播到模板。

但是我没有在Fiddle实体上发现任何Doctrine事件,即使preUpdate占用了实体,也没有调用templates,因为它不需要任何更新。在FiddleTemplate实体上只触发了pre/postPersist事件,但它没有那么大的帮助。

我目前做了一件非常丑陋的事情恕我直言:在坚持之前,我在我的实体上打电话给spreadFiddle

$fiddle->spreadFiddle();
$this->em->persist($fiddle);
$this->em->flush();

该方法如下:

public function spreadFiddle()
{
    foreach ($this->templates as $template)
    {
        $template->setFiddle($this);
    }
}

我的问题来了:

  

是否有更好的方法(使用事件或注释)将Fiddle实体传播到所有模板?

1 个答案:

答案 0 :(得分:1)

制作Fiddle::addTemplate($template)方法不是更好,它会将模板添加到集合($this->templates->add($template))并设置指向self($template->setFiddle($this))的链接。 AFAIK,如果Fiddle是您模型的聚合根,建议采用这种方式。