J'utilise Doctrine
et il ne parvient pas à INSERT
données la première fois que je fais un persist/flush
mais fonctionne la deuxième fois, et échoue la troisième fois :
// there is no code executed between any of the attempts
$entity = new My\Entity();
$entity->setTag('A'); // just a random field
$em->persist($entity);
$em->flush();
// INSERT not performed
// if I exit here and check the database, no entry is added
$entity = new My\Entity();
$entity->setTag('B');
$em->persist($entity);
$em->flush();
// INSERT performed
// if I exit here and check the database, 1 entry has been added
// and I can see it's "B"
$entity = new My\Entity();
$entity->setTag('C');
$em->persist($entity);
$em->flush();
// INSERT not performed
// if I exit here and check the database, there is still only 1 entry added
// and I can see it's "B"
Voici ce que je remarque lors des tentatives ratées :
- Il n'y a rien dans le PHP logs
( error_reporting
est réglé sur tout, les autres problèmes de Doctrine et de PHP, y compris les avertissements, apparaissent dans les journaux).
- Le Doctrine SQLLogger
n'affiche rien (à la deuxième tentative, il affiche l'adresse de l'entreprise). INSERT
).
Quelques étapes de dépannage :
- J'ai voulu pousser plus loin le dépannage en remplaçant la tentative ratée par une DQL
INSERT
demande mais "Les instructions INSERT ne sont pas autorisées dans DQL" :(
- Faire une flush
avant d'instancier $entity
dans l'échec de la tentative n'aide pas - Je peux insérer manuellement autant d'entrées que je veux dans la base de données et cela fonctionne, même à la première tentative.
- J'ai le même problème avec 2.4.0-DEV
.
- J'ai le même problème avec 2.2.2
.
Je pourrais ajouter que le code est exécuté à l'intérieur d'un PHPunit
et que dans un test précédent, je n'ai pas rencontré le problème (c'est-à-dire que Doctrine effectue correctement un test d'identification de l'utilisateur). INSERT
sur le premier persist/flush
).
Une idée de l'origine du problème ?
Infos sur la version :
- PHP 5.4
- Doctrine 2.3.0
( pdo_mysql
conducteur)
- MySQL 5.5.24
- Ubuntu 12.04
- PHPUnit 3.7.7
Mise à jour 1 :
D'accord, voici une partie de la réponse. Le problème semble provenir d'une routine que j'utilise dans mon fichier PHPUnit
setUp()
pour tronquer les tables de ma base de données entre chaque test :
- si je tronque mes tableaux entre chaque test, j'ai des problèmes (c'est-à-dire que certains
INSERT
échouent). - si je ne tronque pas, tout fonctionne bien.
La façon dont le INSERT
semblent être plus aléatoires qu'on ne le pensait au départ, car j'ai créé 2 tests de 3 insertions chacun (et je n'ai exécuté que ceux-là). En tronquant les tables entre chaque test, voici ce qui arrive aux 3 insertions dans chaque test :
-test 1 : SUCCESSE / SUCCESSE / SUCCESSE
-test 2 : SUCCÈS / SUCCÈS / ÉCHEC (je n'ai plus d'ÉCHEC / SUCCÈS / ÉCHEC comme avant).
Voici le morceau de code que j'utilise pour tronquer les tableaux :
$cmd = $em->getClassMetadata($className);
$connection = $em->getConnection();
$dbPlatform = $connection->getDatabasePlatform();
$connection->beginTransaction();
try {
$connection->query('SET FOREIGN_KEY_CHECKS=0');
$q = $dbPlatform->getTruncateTableSql($cmd->getTableName());
$connection->executeUpdate($q);
$connection->query('SET FOREIGN_KEY_CHECKS=1');
$connection->commit();
}
catch (\Exception $e) {
$connection->rollback();
}
J'ai obtenu le code de ce poste SO et pour autant que je puisse voir, ça semble bon. J'ai le même problème si j'utilise cet autre code :
$connection = $entityManager->getConnection();
$platform = $connection->getDatabasePlatform();
$connection->executeUpdate($platform->getTruncateTableSQL('my_table', true /* whether to cascade */));
J'ai modifié mon schéma pour le tester avec et sans les clés étrangères et j'ai le même problème dans les deux cas.