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.
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_A
s 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()