Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Pages: 1
Bonjour,
Je test actuellement Zend_Db pour rendre mon code portable entre les différentes bases de données par contre je suis pas du tout alaise avec les exceptions.
J'aimerai donc savoir quand est ce que vous utilisez try et catch avec Zend_Db et quand est-ce qu'on peut s'en passer?
Je souhaite utiliser que cette partie du framework qui me plais beaucoup mais si je dois mettre un try et un catch dans mon code à chaque fois que je fais une requête je crois que je vais pas y arriver hélas.
Merci d'avance
Luca
Dernière modification par luca (08-03-2009 18:27:46)
Hors ligne
En gros try/catch sert à traiter des cas d'erreurs (connexion à la base ratée, erreur de syntaxe dans ta requête,...).
Le risque si tu ne mets pas de try/catch est que l'internaute voit remonter une exception dans le cas d'une erreur dans ta requête.
Tu peux éviter ça en mettant un try/catch systématique autour de l'ensemble de ton code et si tu reçois une Zend_Db_Exception, tu renvoies vers une page d'erreur. Dans ce cas, tu n'as plus les try/catch à mettre autour de chaque appel à Zend_Db.
Regarde bien le mécanisme des exceptions dans la doc de PHP http://fr2.php.net/manual/fr/language.exceptions.php. Un fois compris le principe, tu verras que tu n'est pas obligé d'en mettre partout tout en traitant correctement le problème.
A+, Philippe
Hors ligne
Salut Philippe, merci pour ta réponse,
C'est une bonne nouvelle que je ne sois pas obligé d'en mettre partout mais est ce que ça reste une bonne pratique de mettre un try/catch uniquement autour de l'ensemble du code?
Ce serait parfait pour moi parce que je n'aime pas du tout ça mais je veux quand même essayer de faire les choses aussi consciencieusement que possible.
En somme les laisser remonter jusqu'au plus haut niveau s'apparenterait à une erreur fatale pour toutes exceptions et je n'ajouterais donc au site que le nécessaire pour les afficher lorsque je suis en développement et à les masquer lorsque le site est en production.
Dernière modification par luca (02-03-2009 13:12:36)
Hors ligne
Si tu n'as pas de traitement hyper critique (du genre appli banquaire, réservation de place d'avion ou autre...), ça peut suffire de faire un gros try/catch global, c'est pas la peine de te prendre la tête.
Il faut te méfier si tu fais plusieurs modifications de base, fichiers,... dans le même traitement. Dans ce cas il faut traiter finement les exceptions pour éviter de mettre tes données dans un état incohérent. Dans des sites simples, c'est rarement le cas.
A+, Philippe
Hors ligne
Merci Philippe tu m'as très bien renseigné.
Les exceptions me paraissent un peu moins mystiques maintenant.
A+, Luca
Hors ligne
Pour bien comprendre l'usage du try catch on peu se référer aux travaux de Meyer. Ce monsieur qui est à l'origine du langage Eifel (Language compilé pur objet à héritage multiple) a proposé depuis très longtemps un modèle de programmation qui permet de clarifier certaine chose.
il part de l'idée que ce n'est pas le même développeur qui crée et qui utilise une méthode.
et que donc implicitement entre les deux développeurs.
Meyer propose de se placer du côté de l'utilisateur de la méthode. nous tous par exemple lorsqu'on emploie une méthode de ZF.
en tant qu'utilisateur des méthode nous avons besoin de savoir comment fonctionnent les méthodes que nous voulons utiliser.
pour cela nous devons connaitre sa finalité mais aussi les paramètres d'entrée leur type et leur bornes nous devons connaitre le type de retour et ses bornes et enfin nous devons savoir ce qui peut empêcher la méthode de fonctionner.
si un développeur utilise la méthode sans respecter ces spécification alors le programme de ce développeur est FAUX et la méthode ne peut absolument pas trouver de solution. elle doit alors provoquer une erreur
dans Eifel c'est direct coredump.
par contre si le développeur respecte les spécification et que la méthode échoue alors elle lève une exception.
meyer propose donc au développeur de la méthode de spécifier tout ces éléments. et de mettre en place ce mécanisme de gestion des erreurs
dans son propre langage il inclus des mots clef permettant de les mettre en œuvre.
une methode est donc définie par sa signature complète type de retour nom type de tout les paramètres.
ensuite il défini un phase qui sera utilisé uniquement lors de la compilation en mode débug
require : là sont vérifié toute les entrées un entrée invalide provoque une erreur fatale (coredump)
compilé en mode normal le require ne génère aucun code
vient ensuite le corps de la méthode
tout appel à un méthode susceptible de remonter une exception DOIT être placé dans un try catch si la méthode en cour d'écriture peu trouver un paliatif ou corriger le problème
par exemple ma méthode doit écrire sur un disque et celui-ci n'est pas accessible
soit ma méthode à une solution de secours (écriture dans un buffer temporaire par exemple) auquel cas on place l'appel de l'écriture dans un try catch soit la méthode n'a pas de solution à proposer et on laisse l'exception remonter à l'appelant cette exception doit alors faire partie du contrat
il y a un autre cas ou on utilise un try catch c'est la formulation d'une exception.
imaginé que je développe une couche de persistance de mes objets dont le support est défini dynamiquement. lorsque une méthode n'arrive pas à accéder à ce support j'ai peut être intérêt à capter l'exception du support physique pour lever une exception propre à ma couche d'abstraction.
avec Zend_Db_Table par exemple une exception de ma classe User qui gère sa persistance dans une table est peut être préférable sous la forme "Utilisateur déjà existant" plutôt qu'une erreur SQL du type Duplicate entry
pour finir pensez à caractériser vos exceptions
pour reprendre l'exemple de ma classe User si je définis mes propres exception User_Exception alors le programme appelant pourra faire la distinction.
try { $myObj->maMethode(); } catch (User_Exception $e) { // traiter ici les exceptions propre à mon application } catch (Zend_Db_Table_Exception $e) { // traiter ici les exception d'accès à la table } catch (Zend_Db_Exception $e) { // traiter ici les exceptions de la base } catch (Zend_Exception $e) { // traiter ici autres les exception } A+JYT
Hors ligne
Merci Sekaijin pour ces explications supplémentaires.
Je crois que je m'y retrouve un petit peu mieux maintenant.
Un petit exemple: une fonction pour vérifier qu'un utilisateur a tapé le bon mot de passe
(je crois que c'est un bon exemple puisqu'il est simple mais qu'il demande de faire particulièrement attention)
function connexion_utilisateur($db,$login,$mot_de_passe){ $select=$db->SELECT() ->FROM('utilisateur',array('id','mot_de_passe')) ->WHERE('login=?',$login) ->LIMIT(1); $res=$db->query($select); if(!$row=$res->fetch(Zend_Db::FETCH_ASSOC)) return false;//Login non trouvé if($row['mot_de_passe']!=$mot_de_passe) return false;//Mot de passe faux else return $row['id']; }
Si j'ai bien compris même cette fonction qui fait très peu de vérifications n'est pas dangereuse puisque toute erreur de connexion ou de requête mal écrite lancera une exception qui arrêtera l'exécution de la page et qu'on pourra attraper avec un try/catch global pour renvoyer l'utilisateur sur une page d'erreur du site.
Hors ligne
c'est une position que tu peux défendre
il y en a d'autre
function connexion_utilisateur($db,$login,$mot_de_passe){ $select=$db->SELECT() ->FROM('utilisateur',array('id','mot_de_passe')) ->WHERE('login=?',$login) ->LIMIT(1); try { $res=$db->query($select); if(!$row=$res->fetch(Zend_Db::FETCH_ASSOC)) return false;//Login non trouvé if($row['mot_de_passe']!=$mot_de_passe) return false;//Mot de passe faux else return $row['id']; } catch (Exception $e) { return false } }
dans ce cas ta fonction ne remonte plus d'exception et donc pour l'appelant c'est comme si l'utilisateur était mal logué. du coup ça lui affichera une page de login fail. cela peut être une bonne stratégie car ainsi tu masque tout problèmes de login. j'entends pas là qu'un hacker ne pourra pas déterminer suite à une erreur de l'application que l'authentification est basée sur une table. moins il a d'info mieux c'est.
ou
function connexion_utilisateur($db,$login,$mot_de_passe){ $select=$db->SELECT() ->FROM('utilisateur',array('id','mot_de_passe')) ->WHERE('login=?',$login) ->LIMIT(1); try { $res=$db->query($select); if(!$row=$res->fetch(Zend_Db::FETCH_ASSOC)) return false;//Login non trouvé if($row['mot_de_passe']!=$mot_de_passe) return false;//Mot de passe faux else return $row['id']; } catch (Zend_Db_Table_Exception $e) { throw new App_Auth_Exception("Auth fail with message : ", $e->getMessage()); } catch (Zend_Db_Exception $e) { throw new App_Auth_Exception("Auth fail with message : ", $e->getMessage()); } }
dans ce cas la comme lorsque tu ne mets rien ta fonction peut remonter des exceptions
la différence c'est que dans un gestionnaire plus général tu pourras distinguer des exception d'accès à la basse des exception d'authentification et donc proposer des traitement mieux adaptés
par exemple ton application utilise un système d'authentification sur LDAP celui-ci est en pane et ne répond pas un exception LDAP te permet de signaler à l'utilisateur que l'annuaire est indisponible mais te ne peut rien faire de plus dans un gestionnaire général
alors que si ton exception est de type auth_adapter exception tu vas pouvoir la distinguer et tenter une authentification de secours sur une base par exemple.
trapper une exception pour en lancer une autre sert donc simplement à la recaolifier en vu de traitements plus adapté
A+JYT
Hors ligne
Merci beaucoup c'est exactement ce que je voulais savoir.
Hors ligne
Pages: 1