Supposons que nous avons deux tables, une représentant des articles et une autre des catégories. On établit une simple relation 1:n entre les deux tables 1 catégorie pouvant avoir plusieurs articles (ça marche aussi avec une relation n:m ou autre...).

Maintenant on imagine que nous voulons différencier l'affichage des catégories pouvant être supprimées et celles ne le pouvant pas car des articles leur sont rattachés.

Le premier réflexe et ce que font la plupart des développeurs c'est de regarder pour chaque catégorie combien d'enregistrements d'articles on trouve.

Pourtant, le plus simple est encore de tester si on peut supprimer la catégorie, et si des articles y sont lié, et bien on nous empêchera la suppression. Et plus le nombre d'articles sera grandissant, plus cette méthode sera préférable car certainement plus rapide. Bien que cela demande à être vérifier. Si quelqu'un possède des chiffres ou veut se lancer dans une petite expérience... j'attends de vos nouvelles ;-)

L'idée donc pour faire ça avec Prado est de faire la suppression dans une transaction et voir si ça marche ou pas, et dans tous les cas, faire un rollback.

Je rappel que Prado (version >= 3.1.x) dans notre cas utilise PDO et que la solution que je propose devrait par conséquent fonctionner avec différents SGBD et même d'autres langages que PHP ;-)

Pour ma part j'utilise ça de façon classique avec l'ensemble Ubuntu + Apache 2 + PHP 5.2 + MySQL 5 + Prado 3.1.1

Comme je n'ai trouvé que peu[1] de référence sur ce sujet j'ai décidé d'écrire moi-même ce petit article après avoir mis en place avec succès la manip tellement c'est simple ;-)

Avec les actives records, une transaction ce fait ainsi sous Prado (exemple pris tel quel dans le tuto de démarrage de Prado):

<?php
 
 $finder = UserRecord::finder();
 $finder->DbConnection->Active=true; //open if necessary
 $transaction = $finder->DbConnection->beginTransaction();
 try
 {
     $user = $finder->findByPk('admin');
     $user->email = 'test@example.com'; //alter the $user object
     $user->save();
     $transaction->commit();
 }
 catch(Exception $e) // an exception is raised if a query fails
 {
     $transaction->rollBack();
 }
?>

Une fois cet exemple adapté à ce que je dis plus haut ça donne le code suivant, qui fonctionne à merveille chez moi ;-)

<?php
# [...]
public function userCanBeDeleted($id){
  $finder = UsersRecord::finder();
  $transaction = $finder->DbConnection->beginTransaction();
  try
  {
    $user = $finder->findByPk($id);
    $user->delete();
    $transaction->rollBack();
    $cr = true;
  }
  catch(Exception $e)
  {
    $transaction->rollBack();
    $cr = false;
  }
  return $cr;
}
# [...]
?>

Voilà, j'espère qu'encore une fois ça rendra service à plusieurs d'entre vous :)

Notes

[1] Pour ne pas dire aucune...