J'ai deux objets PHP compliqués, chacun ayant des données dans quelques tables MySQL.
Parfois, il suffit de supprimer un objet A de la base de données, ce qui prend 3 déclarations SQL. P> Parfois, je dois supprimer un objet B de la base de données, qui prend 4 déclarations SQL et que également strud> a besoin de trouver et de supprimer tout l'objet A de l'objet B possède. P > donc à l'intérieur de la fonction Supprimer_a (), j'exécute ces déclarations à l'intérieur d'une transaction. À l'intérieur de la fonction Delete_B (), je souhaite exécuter une grande grande transaction qui couvre les activités à l'intérieur de Delete_A (). Si tout l'atome d'atome de suppression d'un B échoue, je dois restaurer tous ses A dans le rollback. P> Comment mettre à jour la définition de suppression_a () pour ouvrir une nouvelle transaction Je m'attendais à pouvoir faire quelque chose comme ça, mais l'attribut autocommit code> ne semble pas être modifié par
Begintransaction () Code> P>
function delete_A($a){
global $pdo;
$already_in_transaction = !$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);
if(!$already_in_transaction){
$pdo->beginTransaction();
}
//Delete the A
if(!$already_in_transaction){
$pdo->commit();
}
}
function delete_B($b){
global $pdo;
$pdo->beginTransaction();
foreach($list_of_As as $a){
delete_A($a);
}
$pdo->commit();
}
3 Réponses :
Un moyen est de créer votre propre classe PDoconnect, qui a une variable code> HASTransaction code>. Ensuite, vous venez de vérifier cela. Un exemple peut être trouvé sur les commentaires de la fonction de begintransaction sur php.net ici ici http://www.php.net/manual/fr/pdo.begintransaction.php#81022 p>
Ce serait ma préférence. Accordé cet exemple aura besoin de peaufiner et de s'habiller, etc., mais devrait être une bonne fondation à partir de. p>
Note latérale forte> N'oubliez pas que votre table doit être innodb pour que les transactions fonctionnent. Et puisque vous devez être à Innodb pour que les transactions au travail, vous devriez prendre les conseils de Prodigitaux et utiliser des contraintes de clé étrangère. P>
Vous pouvez appeler Je recommande que les développeurs PHP n'essayent pas de gérer les transactions dans la fonction de fonction ou de la classe. Vous devez gérer les transactions au niveau supérieur de l'application. P>
Voir aussi: p>
PDO :: ATTRE_AUTOCOMMIT CODE> n'est pas un attribut indicateur, c'est un attribut de contrôle. Il contrôle si les déclarations SQL s'engagent implicitement quand elles se terminent. P>
pdo :: intransaction () code> qui retourne
0 code> si vous n'avez aucune transaction en cours et
1 code> si vous avez un transaction en circulation qui doit être commise ou roulée. Cependant, cette fonction n'est pas documentée, il est donc difficile de dire s'il est prudent de dépendre de celui-ci dans toutes les versions futures de PDO. P>
Merci pour les liens, cela m'a conduit à la solution que j'ai fini par utiliser.
intransaction () est maintenant documentée. php.net/manual/fr/pdo.intransaction.php
J'ai fini simplement en utilisant l'exception projetée par et -> Begintransaction () Code> Pour déterminer si j'étais dans une transaction et que j'utilise cela pour décider de commettre la boucle intérieure. Donc
Supprimer_a () Code> a fini par apparaître comme:
delete_b () code> fonctionne sans modification. P> p>
Et si cela est appelé par une autre routine qui a commencé la transaction et décide de retirer? Votre Supprimer sera annulée.
Vous voudrez peut-être envisager d'utiliser des contraintes de clé étrangère (des moyens devront passer de Myisam à un moteur qui les prend en charge) - De cette façon, vous pouvez faire en sorte que les dB ne soient en cascade pour vous au lieu de les émuler.