【问题标题】:Zend2 Doctrine2 One-To-Many uni-directional with join table, delete cascade issueZend2 Doctrine2 One-To-Many 单向连接表,删除级联问题
【发布时间】:2013-03-26 21:32:36
【问题描述】:

我遇到以下问题... 我有一张电话号码表。我想为用户和公司使用同一张表。一个用户也可以有多个电话号码和一个公司。所以我想要一个与两个不同连接表的一对多单向关系。一个将电话号码链接到用户,另一个将电话号码链接到公司。 这是遵循此处找到的教义 2 手册第 5.9 章的解决方案:(click)

我的用户实体持有此代码:

/** @ORM\ManyToMany(targetEntity="Application\Entity\PhoneNumber")
  * @ORM\JoinTable(name="user_phone_number_linker",
  *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
  *      inverseJoinColumns={@ORM\JoinColumn(name="phone_number_id", referencedColumnName="id")}
  *      )
  */
  protected $phone_numbers;

我使用单向一对多,因为我无法制作双向单向,因为如果我引用用户,我无法为公司使用相同的电话号码实体类。现在一切正常,但是当我删除电话号码时,出现以下错误: 执行“DELETE FROM phone_number WHERE id = ?”时发生异常带参数 {"1":1}:

SQLSTATE[23000]:完整性约束违规:1451 无法删除或更新父行:外键约束失败(database/user_phone_number_linker, CONSTRAINT user_phone_number_linker_ibfk_11 FOREIGN KEY (phone_number_id) REFERENCES phone_number (id ))

如果我在数据库中手动设置 ON DELETE CASCADE 值,它可以正常工作,但这不是使用教义 2 的想法,我认为我应该能够在代码中解决它,而无需转到我的 phpMyAdmin 面板。不知何故,应该在删除时启动从电话号码到连接表的级联,但不要从 phone_number 实体返回对连接表的引用。

希望聪明人能帮我解决这个问题。

编辑

与此同时,我学到了更多关于 Doctrine2 的知识,回顾我的旧问题让我意识到,首先将多个电话号码存储在一个表中并不是正确的方法。为了能够将用户电话号码和公司电话号码存储在同一个表中,我应该使用带有鉴别器列的表继承。该列应包含一些用户/公司鉴别器。

由于该列,ORM 学说将“知道”该电话号码实际上是用户还是公司电话号码。我需要在the single table inheritance mapping principles from the doctrine 2 specs 之后进行两个不同的实体定义。

一个类UserPhoneNumber 将与User 具有many-to-one 关系,另一个称为CompanyPhoneNumberone-to-many 关系Company。我不一定需要连接列,user_idcompany_id 列可以在电话号码表中。在User 类中,Company 关联被省略,在Company 类中,User 关联被省略(数据库应该允许这些列的空值)。

如果我确实使用连接表,则根据one-to-many unidirectional with join table description in the Doctrine2 specs

阅读更多

否则,您还可以在this elaborate Doctrine2 in depth website 上阅读有关关联和级联问题的更多信息。

【问题讨论】:

    标签: doctrine-orm zend-framework2 cascade one-to-many joincolumn


    【解决方案1】:

    正如你所说,你的关系是单向的。您已经定义了从用户到电话号码的关系。当您删除用户时,级联删除将起作用,它将删除 user_phone_number_linker 中的所有行,因为这是您定义的关系。

    如果您想以其他方式执行此操作,则必须创建从 PhoneNumbers 到 Users 的关系。教义需要它为你工作。但是您遇到的问题是该实体由其他两个实体用户和公司共享。

    请记住,实体是对象,而不是表。因此,您可以尝试为同一个表创建两个实体,一个名为 PhoneNumberUsers,另一个名为 PhoneNumberCompanies。这样您就可以创建所需的关系来执行级联删除。我没有自己测试过,但我认为它可以工作。

    顺便说一句,您可以删除用户实体连接表上的 oncascade 参数。对于用户和角色,我有与您相同的场景,但我没有使用它。我认为只有当你想从一个实体级联到另一个实体时才需要它。我不确定,但这就是我到现在为止所经历的。

    【讨论】:

    • 感谢您的洞察力。我应该停止在表格中思考并开始在实体中思考。你是对的,那不一样。我显然可以为多个实体重用同一张表!
    【解决方案2】:

    我的错, 电话号码用户关系被认为是多对多关系,因此如果要删除电话号码,我不仅应该删除电话号码本身,而且还必须从用户中显式删除电话号码。所以在Controller中是这样的:

    // Remove the phone number user connection from the database
    $user->removePhoneNumber($phone_number);
    
    // Remove the phone number from the database
    $em->remove($phone_number);
    

    我只是认为使关系与单向一对多的关系的唯一限制足以让教义处理它。那是不正确的。

    【讨论】:

      猜你喜欢
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多