持久化字段时自动传播@OneToMany标识


Automatically spread identity when persisting @OneToMany field

我正在开发twig fiddle,相当于Twig语言的js/sql/php-fiddle。我们可以添加几个模板来呈现结果,我有以下实体:

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 实体的一部分,所以如果我想第一次保留模板,我首先需要保留小提琴。我使用教义事件支持器来做到这一点(如果有兴趣,请参阅修订历史)。但是,如果我尝试将模板添加到已经存在的小提琴并保存,我会得出以下异常:

类型为 Fuz''AppBundle''Entity''FiddleTemplate 的实体缺少 为字段"小提琴"分配 ID。标识符生成策略 此实体要求在 ID 字段之前填充 调用 EntityManager#persist()。如果要自动生成 标识符 相反,您需要调整元数据映射 因此。

听起来很合乎逻辑,因为我需要在持久之前将小提琴的实例传播到模板中。

但是我没有发现任何在 Fiddle 实体上触发的 Doctrine 事件,即使 templates 成为实体的一部分,也不会调用preUpdate,因为它不需要任何更新。在 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 实体传播到所有模板?

制作Fiddle::addTemplate($template)方法不是更好吗,该方法会将模板添加到集合($this->templates->add($template))并将链接设置为自身($template->setFiddle($this))。AFAIK,如果小提琴是模型的聚合根,则推荐使用此方法。