J'utilise cette stratégie pour vérifier les contraintes uniques après que flush() Ce n'est peut-être pas ce que vous voulez, mais ça pourrait aider quelqu'un d'autre.
Lorsque vous appelez flush() si une contrainte unique échoue, une PDOException est lancé avec le code 23000 .
try {
// ...
$em->flush();
}
catch( \PDOException $e )
{
if( $e->getCode() === '23000' )
{
echo $e->getMessage();
// Will output an SQLSTATE[23000] message, similar to:
// Integrity constraint violation: 1062 Duplicate entry 'x'
// ... for key 'UNIQ_BB4A8E30E7927C74'
}
else throw $e;
}
Si vous avez besoin d'obtenir le nom de la colonne défaillante :
Créer des indices de table avec des noms préfixés, par exemple 'unique_'.
* @Entity
* @Table(name="table_name",
* uniqueConstraints={
* @UniqueConstraint(name="unique_name",columns={"name"}),
* @UniqueConstraint(name="unique_email",columns={"email"})
* })
NE PAS spécifier que vos colonnes sont uniques dans la définition de @Column.
Cela semble remplacer le nom de l'index par un nom aléatoire...
**ie.** Do not have 'unique=true' in your @Column definition
Après avoir régénéré votre table (vous devrez peut-être l'abandonner et la reconstruire), vous devriez être en mesure d'extraire le nom de la colonne à partir du message d'exception.
// ...
if( $e->getCode() === '23000' )
{
if( \preg_match( "%key 'unique_(?P<key>.+)'%", $e->getMessage(), $match ) )
{
echo 'Unique constraint failed for key "' . $match[ 'key' ] . '"';
}
else throw $e;
}
else throw $e;
Pas parfait, mais ça marche...
1 votes
Je n'ai pas vraiment de réponse, mais je me demande en quoi le fait de vérifier avant un vidage est si différent que de faire le vidage et de traiter l'erreur (en supposant qu'une clé dupliquée existe).
0 votes
Lors d'une purge, des exceptions spécifiques à la base de données seront lancées.
5 votes
La plupart des solutions présentées ici ne prennent pas en compte le fait que vous venez de ne peut pas vérifier les doublons au préalable, car il ne s'agit pas d'une opération atomique et, par conséquent, vous pouvez todavía ont des valeurs dupliquées, si un autre thread insère dans la table, par exemple. Les seules solutions possibles à mon avis sont soit de gérer l'échec manuellement, soit d'utiliser le verrouillage. La première solution est plutôt moche avec Doctrine (car l'EM est fermé), la seconde peut avoir des conséquences désastreuses sur les performances, si vous n'êtes pas prudent. J'aimerais moi-même trouver une bonne réponse à cette question.