[TUTO] - guestbook, PDO et MVC

Rechercher

[TUTO] - guestbook, PDO et MVC

Par Tef  -  11 reponses  -  Le 25/01/2009 13:22  -  Editer  - 

Salut Hugo.

Ton tuto est super intéressant pour le guestbook, et ça donne une bonne initiation au MVC et le PDO.

Cependant j'ai une petite remarque :

function PDOConnect ($sDSN, $sLogin, $sPassword) {  $oPDO = new PDO($sDSN, $sLogin, $sPassword);  $oPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  return $oPDO;}

Ci-dessous ta fonction intéressante mais qui la facheuse manie d'afficher le mot de passe s'il y a un problème ! De plus aucun formatage donc la lecture est "bordelique". Ca ne vient pas de toi mais simplement du SetAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION).

Ne serait-il pas plus judicieux de faire ceci :

function PDOConnect ($sDSN, $sLogin, $sPassword) {  try {    $oPDO = new PDO($sDSN, $sLogin, $sPassword);  } catch(PDOException $e) {    die ('Erreur : '.$e->getMessage());  }  return $oPDO;}

Voilà ce n'est juste qu'une suggestion hein car je débute dans le l'objet.....et le PDO aussi... (et MVC aussi tiens au passage...) ^__^

Sinon juste une dernière remarque, ton tuto est super intéressant mais dommage que tu n'es pas commenté plus que ça ton code. Tu as super bien expliqué au début le MVC mais d'un seul coup tu as fourni tout le code. J'aurais aimé avoir un peu ton code commenté au fur et à mesure mais bien sur je comprends tout à fait que cela demande pas mal de boulot. Mais sinon super !!

Voilà Hugo.

A+

Stéphane

 

Réponses apportées à cette discussion

Par saturn1  -  Le 25/01/2009 13:37  -  Haut de page  - 

Effectivement il faut faire un try catch!

 
Par Emacs  -  Le 25/01/2009 14:07  -  Haut de page  - 

Effectivement Tef, un try / catch est approprié à cet endroit. J'ai modifié le tutoriel en conséquence :)

 
Par Tef  -  Le 25/01/2009 14:16  -  Haut de page  - 

[Mode Autsatisfation=ON]

Dediou ca fait du bien je commence à piger ^__^

[Mode Autosatisfaction=OFF]

J'ai une autre question et mais je vais faire un autre post :)

Merci à toi

 

Stéphane

 
Par Tef  -  Le 25/01/2009 14:31  -  Haut de page  - 

Par contre tu as laissé cela dans la fonction :

$oPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Est-ce normal ?

 
Par Tef  -  Le 25/01/2009 14:48  -  Haut de page  - 

et le return n'est pas à la fin aussi, est-ce normal ?

 
Par Emacs  -  Le 25/01/2009 14:53  -  Haut de page  - 

J'ai peut-être fait une erreur que tu fais bien de soulever. Je vais tester pour voir si PDO me renvoie une exception si l'instanciation échoue. Par défaut, PDO retourne des erreurs et non des exceptions, d'où le setAttribute() qui vient juste après. Mais si l'instanciation échoue, il ne devrait alors retourner qu'une erreur et pas une exception. Je vais tester ça maintenant pour en être sûr.

 
Par Tef  -  Le 25/01/2009 15:14  -  Haut de page  - 

En fait, si je fais ceci :

function PDOConnect ($sDSN, $sLogin, $sPassword) {
  try {
    $oPDO = new PDO($sDSN, $sLogin, $sPassword);
  } catch(PDOException $e) {
    die ('Erreur : '.$e->getMessage());
  }
  return $oPDO;
}

j'ai pas:

$oPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Pourtant si je me trompe dans un code (exemple le mot de passe), j'ai bien ceci qui apparait :

Erreur : SQLSTATE[28000] [1045] Access denied for user 'root'@'localhost' (using password: YES)

Cela ne suffit-il pas ?

 
Par Emacs  -  Le 25/01/2009 15:29  -  Haut de page  - 

Je viens de tester. En fait, le constructeur de la classe PDO jette bien une PDOException si l'instanciation échoue. Ce n'est qu'ensuite qu'il faut spécifier le niveau d'erreur pour toutes les autres actions appelées sur l'objet PDO. Par défaut, l'objet PDO agit en mode silent, c'est-à-dire qu'il ne renvoie pas d'erreur mais un simple warning comme ci-dessous :

<?php $pdo = new PDO('mysql:host=localhost;dbname=mysql', 'root', ''); foreach ($pdo->query('SELECT * FROM unexistant') as $row){  echo $row->field;}

Me donne :

Warning: Invalid argument supplied for foreach() in /Users/Hugo/Sites/Autres/Demo/Autres/pdo.php on line 6

Avec le niveau d'erreur warning, PDO me génère un message de warning supplémentaire m'indiquant l'erreur retournée par le serveur MySQL :

<?php $pdo = new PDO('mysql:host=localhost;dbname=mysql', 'root', '');$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); foreach ($pdo->query('SELECT * FROM unexistant') as $row){  echo $row->field;}

Me retourne :

Warning: PDO::query() [function.PDO-query]: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'mysql.unexistant' doesn't exist in /Users/Hugo/Sites/Autres/Demo/Autres/pdo.php on line 6 Warning: Invalid argument supplied for foreach() in /Users/Hugo/Sites/Autres/Demo/Autres/pdo.php on line 6

Quant au mode avec exception (celui du tutoriel), PDO jette bien une PDOException en cas d'erreur :

<?php $pdo = new PDO('mysql:host=localhost;dbname=mysql', 'root', '');$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); foreach ($pdo->query('SELECT * FROM unexistant') as $row){  echo $row->field;}

Me donne :

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'mysql.unexistant' doesn't exist' in /Users/Hugo/Sites/Autres/Demo/Autres/pdo.php:6 Stack trace: #0 /Users/Hugo/Sites/Autres/Demo/Autres/pdo.php(6): PDO->query('SELECT * FROM u...') #1 {main} thrown in /Users/Hugo/Sites/Autres/Demo/Autres/pdo.php on line 6

Donc dans le tutoriel, il faudrait que ma fonction PDOConnect soit plutôt celle ci :

<?php /** * Fonction de connexion sur la BDD * * Cette fonction utilise l'extension PDO * de PHP5 * * @param string driver de connexion sur la BDD * @param string login d'accès à la bdd * @param string mot de passe d'accès à la base de données * @param string encodage des données issues de la BDD * * @return PDO objet de connexion sur la BDD **/function PDOConnect($sDbDsn, $sDbLogin, $sDbPassword) {  try  {    $oPDO = new PDO($sDbDsn, $sDbLogin, $sDbPassword);  }  catch (PDOException $e)  {    die('Une erreur interne est survenue');  }   $oPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);   return $oPDO;}

++

 
Par Tef  -  Le 25/01/2009 16:01  -  Haut de page  - 

Ok mais si je suis ton exemple. Je mets une fausse base de données. Ma fonction :

function PDOConnect ($sDSN, $sLogin, $sPassword) {
  try {
    $oPDO = new PDO($sDSN, $sLogin, $sPassword);
  } catch(PDOException $e) {
    die ('Erreur de connexion !');
  }
  $oPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  return $oPDO;
  }

L'erreur retournée :

Erreur de connexion !

Alors ok mais erreur de connexion c'est vague.

Mais par contre si je mets :

function PDOConnect ($sDSN, $sLogin, $sPassword) {
  try {
    $oPDO = new PDO($sDSN, $sLogin, $sPassword);
  } catch(PDOException $e) {
    die ('Erreur de connexion !'.$e->getMessage());
  }
  return $oPDO;
  }

Cela me retourne ceci :

Erreur de connexion !SQLSTATE[42000] [1049] Unknown database 'bdtestz'

Là c'est pas mal mais trop détaillé!! Cela donne des infos tel que le nom de la base. Il y a t'il un compromis ?

A+

Stéphane

 
Par Emacs  -  Le 25/01/2009 16:37  -  Haut de page  - 

Il n'y a pas de compromis. Il faudrait en réalité avoir au moins deux environnements : developpement et production. Ainsi, si tu es en mode développement, tu te permets d'imprimer toute l'exception et sa stack trace pour avoir un maximum d'information sur l'origine du bug. En mode de production, c'est-à-dire quand le site est en ligne, tu ne dois surtout pas afficher ces informations. Une bonne pratique est simplement de retourner un code d'erreur HTTP 500 avec la fonction header() et d'afficher / rediriger vers une page d'erreur 500 personnalisée indiquant à l'utilisateur qu'une erreur interne s'est produite et que tu es désolé pour la gêne occasionnée. Tu peux même par exemple, logguer le message d'erreur dans un fichier et te l'envoyer par mail pour être prévenu que l'erreur s'est produite.

Pour simuler les deux environnements, tu peux te faire une constante et tester sa valeur. Ce qui donne par exemple :

// Dans le fichier de config généraledefine('ENVIRONMENT', 'dev'); // ou 'prod' // Dans le fichier de fonctionsfunction debug($e){  $debug = $e->getMessage();  $debug.= '<br/>';  $debug = $e->getCode();  $debug.= '<br/>';  $debug = $e->getFile();  $debug.= '<br/>';  $debug = $e->getLine();  $debug.= '<br/>';  $debug.= $e->getTraceAsString();   return $debug;} function PDOConnect($sDbDsn, $sDbLogin, $sDbPassword) {  try  {    $oPDO = new PDO($sDbDsn, $sDbLogin, $sDbPassword);  }  catch (PDOException $e)  {    if ('dev' === ENVIRONMENT)    {      echo debug($e);      exit;    }    else    {      // Je loggue l'exception dans un fichier de log du serveur      myLogger::logException($e);       // Je m'envoie un mail      myMailer::sendErrorMail($e);       // Je redirige l'utilisateur sur une page 500      header('HTTP/1.0 500 Internal Server Error');      header('Location: http://www.monsite.com/error500.html');      exit;    }  }   $oPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);   return $oPDO;}

++

Hugo.

 
Par Tef  -  Le 25/01/2009 16:56  -  Haut de page  - 

Mmh moi mettre dans les logs du serveur, j'appelles ça un très bon compromis ;)

Super code merci Hugo.

C'est bon ce soir je dormirais moins c** lol ;)

A+

Stéphane

 

Ajouter une réponse à la discussion

Seuls les membres connectés sont autorisés à poster dans les forums !

Identifiez-vous
Join |  ID/MDP? |