Search code examples
symfony1doctrinesymfony-1.4doctrine-1.2

Doctrine SoftDelete updating parent table


I've got a comments table that is used to store comments for objects in 3 different tables. When I run a functional test on the delete a comment for one of the objects it works fine. However, if I run a functional test for deleting a comment from one of the other objects, I get an integrity constraint MySQL error as doctrine is trying to "update" the first object table as part of deleting the comment associated to an object in table b or c. I can't work out why deleting the comment is trying to update the parent table.

There is a delete cascade from each of the 3 object tables to the comment table. The tables are defined in YML in Symfony 1.4

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

This fault only occurs when running tests via the Symfony 1.4 test harness. It works fine in the dev environment. Prior to object b and c being added object a was a required field but that was removed. I've run symfony cache:clear --env=test to see whether that removed any cached doctrine objects that could be interfering.

EDIT: Now run across the problem in production & development. As far as I can see from the data module and BaseModel files there is no reason for updating the parent table.


Solution

  • After much angst and head-butting-of-the-wall, I worked out what was happening here.

    In this situation it wasn't anything wrong with either the schema or the generated PHP. Instead it occurred due to a postSave() action in the child class. The postSave() action was fetching a property of the parent class, which was already deleted, so Doctrine was in effect creating a new object which it then attempted to save as part of the unit of work. As the new object didn't have any of the required fields, MySQL erorred.

    An example should make it clearer. Object A is the parent object with Object B the child. Object A has a property foo.

    $object_a->delete();
    

    which fires the postSave() action in Object B. This action is:

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

    The $this->Object_As->foo or if using the event $event->getInvoker()->getFoo() will attempt to create an Object_A if none exists. Now, interesting point is if your MySQL table has no required fields this could end up creating lots of new Object_As without you knowing about it until it causes problems elsewhere. I suspect that would be extremely difficult to trace to the culprit.

    In my real usage case I was deleting cache elements. As I am using softDelete, I got around it in this case by checking to see whether the invoker delete field was null e.g:

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