【问题标题】:Doctrine SoftDelete updating parent tableDoctrine SoftDelete 更新父表
【发布时间】:2012-10-23 22:05:56
【问题描述】:

我有一个 cmets 表,用于为 3 个不同表中的对象存储 cmets。当我对删除其中一个对象的注释运行功能测试时,它工作正常。但是,如果我运行功能测试以从其他对象中删除注释,我会收到完整性约束 MySQL 错误,因为教义试图“更新”第一个对象表作为删除与表中对象关联的注释的一部分b 或 c。我无法弄清楚为什么删除评论是试图更新父表。

从 3 个对象表到注释表都有一个删除级联。这些表在 Symfony 1.4 中的 YML 中定义

object_a:
  columns:
    some stuff
  relations:
    Comments:
      class: Comments
      local: id
      foreign: object_a_id
      type: many
      foreignType: one
      cascade: [delete]

object_b:
  columns:
    some stuff
  relations:
    Comments:
      class: Comments
      local: id
      foreign: object_b_id
      type: many
      foreignType: one
      cascade: [delete]

object_c:
  columns:
    some stuff
  relations:
    Comments:
      class: Comments
      local: id
      foreign: object_c_id
      type: many
      foreignType: one
      cascade: [delete]

comments:
  columns:
    object_a_id:
       type: integer(4)
    object_b_id
       type: integer(4)
    object_c_id
       type: integer(4)
  relations:
    Object_a:
       local: object_a_id
       foreign: id
       type: one
    Object_b:
       local: object_b_id
       foreign: id
       type: one
    Object_c:
       local: object_c_id
       foreign: id
       type: one

此故障仅在通过 Symfony 1.4 测试工具运行测试时发生。它在开发环境中运行良好。在添加对象 b 和 c 之前,对象 a 是必填字段,但已被删除。我已经运行了 symfony cache:clear --env=test 来查看是否删除了任何可能干扰的缓存学说对象。

编辑: 现在在生产和开发中遇到问题。据我从数据模块和 BaseModel 文件中可以看出,没有理由更新父表。

【问题讨论】:

  • 如果外键生成正确,你能检查生成的 SQL 吗?我一直在关系定义中使用符号“onDelete: cascade”。
  • onDelete:级联是数据库级别,我正在使用应用程序级别的删除。我通过试验发现一个错误,这是由于发生的一些 postDelete() 操作实际上创建了一个新的父对象。我会添加一个更完整的解释,因为如果您不寻找它,这是一个问题。

标签: symfony1 doctrine symfony-1.4 doctrine-1.2


【解决方案1】:

在经历了很多焦虑和头疼之后,我弄清楚了这里发生了什么。

在这种情况下,架构或生成的 PHP 都没有问题。相反,它是由于子类中的 postSave() 操作而发生的。 postSave() 操作正在获取父类的属性,该属性已被删除,因此 Doctrine 实际上是在创建一个新对象,然后尝试将其保存为工作单元的一部分。由于新对象没有任何必填字段,MySQL 出错。

一个例子应该更清楚。 Object A 是父对象,Object B 是子对象。 Object A 有一个属性 foo

$object_a->delete();

触发Object B 中的postSave() 动作。这个动作是:

function postSave($event) 
{
  //do something
  $slug = $this->Object_As->foo;
  //do more stuff
}

$this->Object_As->foo 或如果使用事件 $event->getInvoker()->getFoo() 将尝试创建一个 Object_A(如果不存在)。现在,有趣的一点是,如果您的 MySQL 表没有必填字段,这最终可能会在您不知道的情况下创建许多新的Object_As,直到它在其他地方引起问题。我怀疑这很难追查到罪魁祸首。

在我的实际使用案例中,我正在删除缓存元素。当我使用softDelete时,我通过检查invoker删除字段是否为空来绕过它,例如:

$event->getInvoker()->getDeleted_at()      

【讨论】:

  • 这是一个奇怪的案例,删除操作会触发 postSave。似乎更合乎逻辑的是,即使记录没有真正删除,也会触发后/前删除而不是保存。当然,应该保存字段,但它应该阻止前/后保存事件并触发前/后删除。无论如何,感谢您回来解释您的解决方案。你现在应该接受你自己的答案:)
  • 它会触发postSave(),因为系统正在使用保存删除日期的软删除。我还应该注意这是级联删除。 Object_A 被删除,将删除级联到 Object_B。我从未测试过它,但它可能会触发 postDelete() 行为。这几乎感觉像是一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-28
  • 2014-06-13
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 1970-01-01
  • 2016-12-24
相关资源
最近更新 更多