Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Récupérer erreur Try Catch


Sujet :

PHP & Base de données

  1. #1
    Membre régulier
    Récupérer erreur Try Catch
    Bonjour,
    J'ai des requêtes de ce style (depuis qqls années)
    Code php :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    try { $sql = "SELECT * FROM users ";
      $stmt = $bdd_user->prepare($sql);
      $stmt->execute(array());
      while ($results=$stmt->fetch(PDO::FETCH_ASSOC)) {
        $array_users[$results['id']]=$results;
      }
    } catch(PDOException $e) {echo 'Erreur: '.$sql . "<br>" . $e->getMessage();}

    et je me disais
    que je n'ai jamais vu le {echo 'Erreur: '.$sql . "<br>" . $e->getMessage();} du catch

    Loin s'en faut que je n'ai jamais eu d'erreur dans mes requêtes...

    Cela correspond-t-il aux message d'erreurs orange ?
    Pourrait-on faire ?
    Code php :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    catch(PDOException $e) {
    $erreur=1;
    $requete=$sql;
    }
    Puis en bas de page
    Code php :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    if(isset($erreur)) {
    // > s'envoyer un mail avec la $requete; 
    }
    "Ils ne savaient pas que c'était impossible, alors ils l'ont fait." Mark Twain

  2. #2
    Membre expérimenté
    Salut,

    Dans ce cas là tu peux mettre l'envoi de mail directement dans le catch puisque tu es certains si tu es dedans que tu as eu une exception. Pourquoi faire une requête préparé si tu n'utilises pas de paramètres extérieurs? Le try catch ici à vraiment une utilité? Car ici tu récupères les utilisateurs donc au pire la table utilisateur n'existe pas donc là c'est l'application qui down.
    Juste un avis

  3. #3
    Modératrice

    Par défaut, PDO est en mode silencieux. Autrement dit, si quelque chose plante, ben ça plante, point. Si tu veux des exceptions, il faut les activer au niveau de la connexion.
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  4. #4
    Expert éminent
    Oui tu pourrais le faire sans problème si cela te sert pour une meilleure organisation de ton code, on peut faire n'importe quoi dans le catch, à condition qu'il soit opérationnel et puisse se déclencher en cas d'erreur comme l'a dit Celira.

  5. #5
    Membre régulier
    Ok, merci pour les réponses.
    Citation Envoyé par Celira Voir le message
    Par défaut, PDO est en mode silencieux. Autrement dit, si quelque chose plante, ben ça plante, point. Si tu veux des exceptions, il faut les activer au niveau de la connexion.
    Apparemment pour activer les exceptions il faut
    "dé commenter dans le fichier php.ini les modules pdo. " (dixit un post)
    Et comment cela se passe une fois le site hébergé ?
    "Ils ne savaient pas que c'était impossible, alors ils l'ont fait." Mark Twain

  6. #6
    Modératrice

    Citation Envoyé par feelwatt Voir le message
    "dé commenter dans le fichier php.ini les modules pdo. "
    Nope, ça c'est pour activer PDO tout court. Pour les exceptions, c'est à faire au niveau de la connexion :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  7. #7
    Rédacteur/Modérateur

    Bonjour,



    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
                $pdo = new PDO('mysql:host=localhost;port=3306;dbname=ma_base;charset=utf8','root', '', [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // ACTIVATION des erreurs PDO
                PDO::ATTR_EMULATE_PREPARES => false
                ]);

    Perso, j'ajoute :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
     
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, 	// fetch mode par defaut
                PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",	// encodage UTF-8
    "Si tu suis le chemin qui s'appelle « plus tard », tu arriveras à la place qui s'appelle « jamais »."
    François Camille Prévot (1910-1996), instituteur puis Directeur d'école et... mon grand-père.
    "Pose ta question, tu seras idiot une seconde. Ne la pose pas, tu seras idiot toute ta vie."
    Albert Einstein (1879-1955).
    Mes tutos DVP
    Gestion-Affichage de Nouvelles
    Affichage en tableau HTML
    Fonctions de redimensionnement d'images

  8. #8
    Membre régulier
    Citation Envoyé par Celira Voir le message
    Nope, ça c'est pour activer PDO tout court. Pour les exceptions, c'est à faire au niveau de la connexion :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    Ah ok, je vais tenter ca. Merci.
    "Ils ne savaient pas que c'était impossible, alors ils l'ont fait." Mark Twain

  9. #9
    Membre régulier
    Ok,
    C'est là
    Code php :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    try
    {	
    $bdd_user = new PDO('mysql:host=localhost;dbname=users', 'root', '');
    $bdd_user->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch(Exception $e)
    {
    die('Erreur : '.$e->getMessage());
    }
    Comme ca si ca merdoit, je m'envoi un mail.
    Merci Célira
    "Ils ne savaient pas que c'était impossible, alors ils l'ont fait." Mark Twain

  10. #10
    Membre régulier
    A super, Jreaux
    Je vais poser ca.
    "Ils ne savaient pas que c'était impossible, alors ils l'ont fait." Mark Twain

  11. #11
    Expert éminent
    @jreaux62
    Qu'apporte PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" puisque tu indiques déjà le charset dans le premier paramètre de la connexion $pdo = new PDO('mysql:host=localhost;port=3306;dbname=ma_base;charset=utf8',... ? Une erreur d'inattention je suppose ?

    Enfin bon, c'était plutôt pour dire qu'il y a un point sur lequel je ne suis pas d'accord dans le tuto mentionné en lien, c'est celui de conseiller de fermer la connexion PDO. Cela ne sert à rien car Php fermera la connexion tout seul dès qu'il n'en aura plus besoin, et en même temps c'est ingérable quand les scripts deviennent un peu compliqués (imbrication etc.). C'est donc contre productif car on se prend la tête pour rien.

  12. #12
    Membre chevronné
    Bonjour,

    Le charset à la connexion permet de définir dans quel charset on va travailler. Cela comprend à la fois également le charset du fichier PHP mais aussi celui du document HTML qui sera output.
    Le SET NAMES, quant à lui, est une requête SQL qui permet de forcer l'output de SQL dans un charset (en TRES GROS, SQL va automatiquement faire un utf8_encode() avant de retourner les valeurs)

    C'est une astuce qui date de l'époque où on est passé du charset ISO au charset UTF8. Pour ne pas devoir ALTER tous les champs de nos tables pour changer le bon vieux latin1_swedish_ci (ou un truc dans le gendre, ça fait longtemps maintenant ) qui était le charset par défaut pour l'ISO à l'époque

    Les charsets c'est compliqué ^^

    EDIT :
    Il est conseillé de TOUJOURS fermer une connexion SQL.
    C'est peut-être inutile pour toi en tant qu'humain qui ne voit pas l'intérêt de gagner 1s de trajet sur ton chemin maison <-> travail mais 1s dans le monde l'informatique, c'est tout simplement ENORME ! D'autant qu'ici je ne parle que de "temps" mais ils faut aussi prendre en compte la mémoire allouée pour ton script PHP/SQL.

  13. #13
    Expert éminent
    Citation Envoyé par darkstar123456 Voir le message
    Les charsets c'est compliqué ^^
    Oui j'en sais quelque chose, j'ai fait un tuto là dessus en 2008 pour le passage à l'UTF8. On peut le retrouver facilement en tapant "tuto utf-8 phpfrance" dans un moteur de recherche.
    Et je confirme au passage que la déclaration charset=utf8 dans le premier argument de l'initialisation de pdo permet à mysql de travailler en utf-8 (sans besoin de rajouter set Names).

    Citation Envoyé par darkstar123456 Voir le message
    EDIT :
    Il est conseillé de TOUJOURS fermer une connexion SQL.
    C'est peut-être inutile pour toi en tant qu'humain qui ne voit pas l'intérêt de gagner 1s de trajet sur ton chemin maison <-> travail mais 1s dans le monde l'informatique, c'est tout simplement ENORME ! D'autant qu'ici je ne parle que de "temps" mais ils faut aussi prendre en compte la mémoire allouée pour ton script PHP/SQL.
    Re non. La déconnexion manuelle n'est conseillée que pour les requêtes persistantes, ou encore si tu as des tonnes de code ou un traitement très long derrière ta requête. Dans les autres cas c'est un inutile et contre productif car avec un code un peu compliqué tu vas devoir ouvrir une connexion pour chaque requête pour la refermer ensuite, ce qui pour le coup est beaucoup plus pénalisant pour les performances. Et pour un code standard plus simple on ne gagne rien donc dans la pratique on ne s'en occupe pas sauf exception.

    Pour le reste on peut toujours utiliser closeCursor() pour libérer les ressources. C'est sans inconvénient car cela ne pose jamais de problème mais ce n'est indispensable que pour certains gestionnaires de base de donnée et ne concerne pas mysql par exemple.

  14. #14
    Rédacteur/Modérateur

    Citation Envoyé par ABCIWEB Voir le message
    Qu'apporte PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" puisque tu indiques déjà le charset dans le premier paramètre de la connexion $pdo = new PDO('mysql:host=localhost;port=3306;dbname=ma_base;charset=utf8',... ? Une erreur d'inattention je suppose ?
    @ABCIWEB
    Non, je pense que j'ai dû (autrefois *) ajouter l'un sans voir qu'il y avait déjà l'autre.
    Depuis, je ne me suis pas posé la question... et je les ai laissés (c'est la ceinture ET les bretelles !)

    * (Quand j'ai passé mes 1ers sites en mysql_/ISO en PDO/UTF-8)

    ...c'était plutôt pour dire qu'il y a un point sur lequel je ne suis pas d'accord dans le tuto mentionné en lien, c'est celui de conseiller de fermer la connexion PDO. Cela ne sert à rien....
    Tu as raison, et j'en avais parlé à Dendrite.
    A la suite de quoi elle a ajouté (voir 3b - PDO - fermer la connexion, c'est bien.) :
    [...]...vous ouvrirez la connexion, vous ferez peut-être dix requêtes, de select, d'update, d'insert, toujours avec la même connexion et vous ne la fermerez qu'en fin de page.
    "Si tu suis le chemin qui s'appelle « plus tard », tu arriveras à la place qui s'appelle « jamais »."
    François Camille Prévot (1910-1996), instituteur puis Directeur d'école et... mon grand-père.
    "Pose ta question, tu seras idiot une seconde. Ne la pose pas, tu seras idiot toute ta vie."
    Albert Einstein (1879-1955).
    Mes tutos DVP
    Gestion-Affichage de Nouvelles
    Affichage en tableau HTML
    Fonctions de redimensionnement d'images

  15. #15
    Expert éminent
    Citation Envoyé par jreaux62 Voir le message
    @ABCIWEB
    Non, je pense que j'ai dû (autrefois *) ajouter l'un sans voir qu'il y avait déjà l'autre.
    Depuis, je ne me suis pas posé la question... et je les ai laissés (c'est la ceinture ET les bretelles !)

    * (Quand j'ai passé mes 1ers sites en mysql_/ISO en PDO/UTF-8)
    Oui, et puis initialement on ne pouvait pas déclarer le charset dans le premier argument de l'initialisation de Pdo avec mysql, setname était la seule solution. Cette option est arrivée un peu plus tard avec une version de mysql et tu t'es sans doute inspiré de différents tutos à l'époque.

    Pour dire au passage que cette possibilité dépend du gestionnaire de base de données et que dans l'absolu setname est plus universel puisqu'il ne dépend que de pdo. Mais bon quand on change de sgbd, normalement on se renseigne et il est fort probable que tous les sgbd supportent maintenant cette possibilité (je n'utilise pas MariaDB mais ce doit être identique puisqu'il a été conçu par la même personne qui a conçu mysql). Et puis comme utf-8 est devenu le charset universel du web, autant l'indiquer dans la connexion ce qui permet de mieux se concentrer sur les options.

    Après peut-être que tout comme php, mysql soit maintenant configuré par défaut en utf-8 chez la plupart des hébergeurs. C'est déjà le cas chez OVH qui par défaut utilise utf8mb4_unicode_ci sur les mutualisés. utf8mb4 permet d'enregistrer des symboles et des emojis. Pour ceux que cela intéresse plus d'info ici.

  16. #16
    Membre régulier
    Salut à tous,
    J'ai suivi vos réponse sans avoir le niveau de précision que vous avez....

    J'ai (réussi) à avoir une erreur
    Erreur: UPDATE cgv SET num=? titre=?, texte=? WHERE id=?
    SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'titre='Titre 01', texte='Text 01 ' WHERE id='1'' at line 1
    Erreur: UPDATE discutions SET num=? titre=?, texte=? WHERE id=?
    Donc ca donne toutes les infos sur la requête, super.
    > Mais est-ce l'on pourrait envoyer dans les post des codes qui engendreraient ce type d'erreur,
    et donc voir toute la requête ? (pour mieux craquer la BD).
    "Ils ne savaient pas que c'était impossible, alors ils l'ont fait." Mark Twain

  17. #17
    Rédacteur/Modérateur

    Citation Envoyé par feelwatt Voir le message
    J'ai (réussi) à avoir une erreur


    Sinon, ce genre d'affichage est a réserver à la phase de TEST du site !
    En production : on évite justement tout type d'affichage susceptible de donner trop d'informations.
    "Si tu suis le chemin qui s'appelle « plus tard », tu arriveras à la place qui s'appelle « jamais »."
    François Camille Prévot (1910-1996), instituteur puis Directeur d'école et... mon grand-père.
    "Pose ta question, tu seras idiot une seconde. Ne la pose pas, tu seras idiot toute ta vie."
    Albert Einstein (1879-1955).
    Mes tutos DVP
    Gestion-Affichage de Nouvelles
    Affichage en tableau HTML
    Fonctions de redimensionnement d'images

  18. #18
    Membre régulier
    Ok,
    c'est ca le truc,
    je vais donc mettre un
    Code php :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    if ($_SERVER['REMOTE_ADDR']=="127.0.0.1") { 
    $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    Merci
    "Ils ne savaient pas que c'était impossible, alors ils l'ont fait." Mark Twain

  19. #19
    Expert éminent
    Oui mais tu n'es pas obligé d'être aussi radical, dans le sens où en cas d'erreur les visiteurs n'auront plus aucun message, pas plus que toi sur le serveur distant. On peut aussi faire un mixte des deux qui renverra une information d'ordre général aux visiteurs et le détail en test local. Ainsi si un visiteur a un problème tu sauras plus vite où chercher. Par exemple:

    Code php :Sélectionner tout -Visualiser dans une fenêtre à part
    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
    function dieErrorSql ($e, $v)
    {
        exit($_SERVER['REMOTE_ADDR'] == "127.0.0.1" ? 'Erreur : '.$e->getMessage() : 'Erreur : '.$v);
    }
     
     
    try
    {
        // requête insertion produit	
        $query = ....;
    }
    catch(Exception $e)
    {
        dieErrorSql ($e, "Problème dans la requête d'insertion du produit");
    }
     
    //...
    try
    {
        // requête suppression produit	
        $query = ....;
    }
    catch(Exception $e)
    {
        dieErrorSql ($e, "Problème dans la requête de suppression du produit");
    }


    L'intérêt est que ton exception est toujours levée, avec un message détaillé en local, et suffisamment précis pour les visiteurs mais sans jamais leur envoyer d'informations confidentielles.

  20. #20
    Membre régulier
    OK, super ABCIWEB
    je vais étudier ça.
    "Ils ne savaient pas que c'était impossible, alors ils l'ont fait." Mark Twain