Transactions dans SGBD à l’aide de Zend Framework

Ce petit tutorial qui concerne les transactions à l’aide de Zend Framework est basé sur les versions suivante :

Les transactions dans une base de données

Les bases de données définissent les transactions comme étant des unités logiques de travail qui peuvent êtres validées (commited) ou annulées (rolled back) en tant qu’une seule opération, même sur de multiples tables. Toutes les requêtes aux bases de données sont considérées comme faisant partie d’une transaction, même si le driver de base de données fait ceci implicitement. Ceci s’appelle le mode auto-commit, dans lequel le driver de base de données créer une transaction pour chaque requête executée et la valide. Par défaut toutes les classes Zend_Db_Adapter fonctionnent en mode auto-commit.

Source : Zend Framework

Vous l’aurez compris, les transactions représentes un groupe de requêtes qui pourra être validé si tout se passe bien ou dans la cas contraire annulé.

Pour diverses raisons, il peut être utile d’effectuer une transaction vers une base de données.
Il va de soit que pour utiliser les transactions, votre SGBD et votre moteur de stockage doivent pouvoir les gérer. Ce qui est le cas d’INNODB pour MySQL mais pas encore pour MyISAM.

Donc si votre moteur de stockage est MyISAM, vous devrez convertir les tables qui seront concernées par vos futurs transactions.

Changement du moteur de stockage
On peut changer dynamiquement le moteur de stockage à l’aide de la commande ALTER TABLE.

Pour passer le moteur de stockage de la table leNomDeMaTable en INNODB nous effectuerons la commande sql suivante :

1
    ALTER TABLE leNomDeMaTable ENGINE=INNODB;

Pour le passer en MyISAM :

1
    ALTER TABLE maTable2 ENGINE=MYISAM;

Transactions à l’aide de Zend Framework
Maitenant que notre SGBD gère les transactions, il va falloir spécifier manuellement le démarrage de la transaction à l’aide de beginTransaction(). Toutes les requêtes qui suivront feront parties de celle-ci tant que la transaction ne sera pas annulée avec rollBack() ou validée par un commit().

Le canevas de base sera donc :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
$db->beginTransaction();
 
try {
    // Essaye d'exécuter une ou plusieurs requêtes :
    $db->query(...);
    $db->query(...);
    $db->query(...);
 
    // Si toutes ont réussi, valide les changements en une seule passe.
    $db->commit();
}
catch (Exception $e)
{
    // Si une des requête s'est mal déroulée, alors nous voulons annuler les changements
    // de toutes les requêtes faisant partie de la transaction, même celles qui se sont
    // bien déroulées. Tous les changements sont annulés d'un seul coup
    $db->rollBack();
    echo $e->getMessage();
}
?>

Transactions dans en MVC avec Zend Framework
Imaginons que nous avons des produits divers. Ceux-ci sont enregistrer dans une la base de données.
Les informations communes à tous les produits sont enregistrées dans la table Produit et toutes les données spécifiques à chaque type de produit dans la table correspondant au type : ProduitNomDuType.

Nous aurons donc les modèles Produit qui est une classe qui héritera de Zend_Db_Table_Abstract et Produit_Row qui héritera de Zend_Db_Table_Row_Abstract (nous aurons la même chose pour gérer les tables et ligne des ProduitNomDuType).

Pour ajouter un produit du type Foo nous allons donc devoir remplir la table « générique » Produit et ProduitFoo.
Nous allons donc créer une transaction qui effectuera l’insertion des données dans les 2 tables.

Ce qui pourrait nous donner dans l’action ajouterAction() de notre controller quelque chose comme :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
// ...
 
// On récupère l'adaptater que nous avons sauvé dans le registry dans le boostrap
$db = Zend_Registry::get('db');	
 
// On démarre la transaction
$db->beginTransaction();
 
try {
	Zend_Loader::loadClass('Produit');
	Zend_Loader::loadClass('ProduitFoo');
	$produitDb = new Produit($db);
	$produitDb->insert($dataProduit);  // $dataProduit est un tableau qui représente les données générique du produit
 
	$produitFooDb = new ProduitFoo($db);
	$produitFooDb->insert($dataProduitFoo);  // $dataProduitFoo est un tableau qui représente les données spécifique du produit foo
 
	// On valide l'ensemble des requêtes
	$db->commit();
}
catch (Exception $e)
{
	// Si une exception a été levée, on annule toutes les opérations du lot
	$db->rollBack();
 
	//...
}

Cette transaction permettra par exemple de ne pas se retrouver avec juste les infos génériques du produit si l’ajout des infos dans ProduitFoo a levé une exception.

Quelques liens utiles

N’hésitez pas à poser vos questions ou remarques dans les commentaires, je me ferais un plaisir d’y répondre.

Note: je ne me suis pas étendu sur le fonctionnement du MVC avec Zend Framework vu qu’il y a énormément de chose à dire et que cela fera partie d’un futur tutorial.

Bookmark and Share
Hervé — 11 juillet 2008 @ 17:22 Filed under: Tuto MySQL,Tuto Php,Tuto Zend Framework,Tutorial Tag: , , ,

Pas de commentaire »

Pas encore de commentaire.

Flux RSS des commentaires de cet article. TrackBack URL

Laisser un commentaire