Php 一对多关系和多对一原则

Php 一对多关系和多对一原则,php,symfony,doctrine-orm,cascade,relationships,Php,Symfony,Doctrine Orm,Cascade,Relationships,我有两张桌子。我想建立一对多的关系,但也要建立一对多的关系 一个页面可以有一个背景-这是页面的背景 一个页面也可以有很多背景-这是一个用户上传的背景的集合,其中一个将被选择为第一个关系 换句话说,用户从一堆预定义的背景中选择一个背景,或者从他上传的许多背景中选择一个进行尝试 编辑:删除背景时,我希望所有具有该背景id的页面的背景id都设置为空。删除页面时,我希望删除属于该页面的所有自定义背景 虽然doctrine和symfony允许上述配置,但在删除页面时,doctrine会完全忽略Backgr

我有两张桌子。我想建立一对多的关系,但也要建立一对多的关系

一个页面可以有一个背景-这是页面的背景

一个页面也可以有很多背景-这是一个用户上传的背景的集合,其中一个将被选择为第一个关系

换句话说,用户从一堆预定义的背景中选择一个背景,或者从他上传的许多背景中选择一个进行尝试

编辑:删除背景时,我希望所有具有该背景id的页面的背景id都设置为空。删除页面时,我希望删除属于该页面的所有自定义背景

虽然doctrine和symfony允许上述配置,但在删除页面时,doctrine会完全忽略Backgrounds属性上的cascade={remove},当然,在删除页面的自定义背景之前尝试删除页面时会引发异常

我做错了什么

class Background
{
/**
 * @var string
 *
 * This attribute is for user uploaded backgrounds.
 *
 * @ORM\ManyToOne(targetEntity="Page",inversedBy="customBackgrounds")
 * @ORM\JoinColumn(name="page_id",referencedColumnName="id")
 */
protected $page;

/**
 * @var string
 *
 * This field helps admins to gauge popularity
 *
 * @ORM\OneToMany(targetEntity="Page",mappedBy="background")
 */
protected $pages;
}


class Page
{
/**
 * @var string
 *
 * @ORM\ManyToOne(targetEntity="Background",inversedBy="pages")
 * @ORM\JoinColumn(name="background_id",referencedColumnName="id", nullable=true, onDelete="SET NULL")
 */
protected $background;

/**
 * @ORM\OneToMany(targetEntity="Background", mappedBy="page", cascade={"remove"})
 * @ORM\OrderBy({"id" = "ASC"})
 */
protected $customBackgrounds;
}

您唯一能做的就是在实体中使用事件侦听器,当删除页面时,将其背景设置为null或另一个id @ORM\JoinColumnname=page\u id,referencedColumnName=id,onDelete=SET NULL并执行架构更新

编辑:问题出在数据库级别,而不是条令级别,cascade=remove解决了这个问题,但是page_id的外键保持不变,onDelete表示如果删除了具有该外键关系的列,则将该字段设置为null。如果在模式更新之前-dump sql,您将看到查询添加,类似于ON DELETE SET*

更多信息可在此处找到:


应该做到这一点

我应该提到,删除$background属性和多通关系注释可以在删除页面时完美地恢复cascade remove功能删除其自定义背景-但这当然不是我想要做的。Dariushp成功地解决了我的问题,但对我来说毫无意义。当我删除时,我使用cascade={remove}来删除其他相关对象,而不使用onDelete=SET NULL来删除这些对象。我不理解当删除父对象时,onDelete=SET NULL在dbms级别对孤立相关对象起作用。当父对象被删除时,这对删除相关对象有何帮助?但这难道不会在我删除页面时孤立自定义背景吗?我已经尝试过了,但得到了相同的错误:在使用params[16]:SQLSTATE[23000]执行“delete FROM page WHERE id=?”时发生异常:完整性约束冲突:1451无法删除或更新父行:外键约束使项目失败。背景,约束FK_F335B7807B40E4F7外键页面id引用页面id策略,我再次尝试了您的答案,它确实有效-并且背景实际上已被删除-这不是我所期望的。谢谢@dariusphp!如果您可以编辑您的答案,以提供合理的解释,说明为什么这样做有效,我将授予您奖金。好的,该页面向我解释了我已经知道的内容-onDelete SET NULL会使子表上的外键为空,但子表中的记录不会被删除。Doctrine的文档从未建议您将此条件添加到要级联删除的子表中,我过去也没有在任何其他情况下使用过它。事实上,我还有其他与页面实体相关的子实体,它们在不添加此条件的情况下被级联删除。只有当我以另一种方式恢复第二段关系时,这才显得必要。这是为什么?但我希望在删除页面时删除自定义背景,并且在删除背景时将页面的背景id设置为null。。。
/**
 * @ORM\OneToMany(targetEntity="Background", mappedBy="page", orphanRemoval=true)
 * @ORM\OrderBy({"id" = "ASC"})
 */
protected $customBackgrounds;