We have a weird problem in our project where certain Doctrine entities are not being saved. The problem does not occur every time but intermittently and we have no idea what's causing it.
We have two linked entities that are saved thus:
$one = (new One)
->setValues()
...
;
$two = (new Two)
->setOne($one)
->setUser($user)
;
$em->persist($one);
$em->persist($two);
$em->flush();
The relationships/entities are defined as follows:
class User {
...
/**
* @var Two[]|Collection
* @ORM\OneToMany(targetEntity="Two", mappedBy="user")
*/
private $twos;
...
}
class One {
...
/**
* @var Two[]|Collection
* @ORM\OneToMany(targetEntity="Two", mappedBy="one")
*/
private $twos;
...
}
Class Two {
...
/**
* Note this field in the db is an auto-increment
* @ORM\Column(name="two_id", type="integer")
*/
private $id;
/**
* @var One
* @ORM\Id()
* @ORM\ManyToOne(targetEntity="One", inversedBy="twos")
* @ORM\JoinColumn(name="one_id", referencedColumnName="one_id")
*/
private $one;
/**
* @var User
* @ORM\Id()
* @ORM\ManyToOne(targetEntity="User", inversedBy="twos")
* @ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
*/
private $user;
...
}
We are not seeing any errors, and when we enable debug logging in DBAL we can see log entries for the start of the transaction, all inserts (including for Two
) and for the commit. We cannot reproduce the problem locally so cannot use a step debugger to work through it. Most of the time both entities are saved but not every time.
If we clear the Two
entity from the ObjectManager and try to reload it from the database, it is showing that it does have an id.
$em->clear(Two::class);
$two = $twoRepository->findTwo($user, $one);
if ($two) {
$logger->info('Two created', ['two' => $two->getId(),]);
}
Now, when we get an occurrence of Two
not being saved, we can see a log which is outputting an id but when we then check the relevant db table, there is no row with that id in it.
No exceptions are thrown at any point and we cannot see any other log that might indicate a problem.
We have no idea what might be happening. The fact that the entity is given an auto-increment but isn't saved suggests that perhaps there is a problem in the db transaction. But, as I understand it, the transaction would happen within the call to flush()
and there is no indication of that transaction having to be rolled back. Plus the subsequent call to reload the entity from the db happens after that so Doctrine must either be retrieving that entity from the database or from it's internal object store (although it's mu understanding that the clear()
should mean it has to go back to the db to load that entity).