I have an entity called Contact
with a single unique field email
. Also I have a form type used intended for an admin interface, let's call it ContactType
. Everything described below happens using a form built with ContactType
:
Let's assume I want to add a contact with an email mr.validated@example.com
, of course it works. Then I try again and bam, validation kicked in, error message says what happened. Perfect!
Now I want to add another contact, this time with an email mr.race.condition@example.com
, but oops, I accidentally submitted the form twice! Both requests are processed like this:
| Request 1 | Request 2
-+-----------------+-----------------
1| $form->bind() | $form->bind()
2| Validation | Validation
3| $em->flush() | $em->flush()
In both cases validation passed since the Contact
entity with such email wasn't in database yet. This leads to two Insert
queries with the same email. MySQL will prevent the second one, so Doctrine will throw an exception, user will see error 500 instead of "Email has been already taken".
My question is: How do I make Symfony handle that for me? I just want to tell the user that he have to type in different email address.
I could of course do something like this:
try {
$this->getDoctrine()->getManager()->flush();
} catch (DBALException $e) {
$pdoException = $e->getPrevious();
if ($pdoException &&
$pdoException instanceof PDOException &&
$pdoException->getCode() === '23000'
) {
// let the form know about the error
} else throw $e;
}
But that's wrong, requires copy-pasting the code each time I have to deal with unique constraints, and is trouble in case there is more than one unique index.