IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Langage PHP Discussion :

Gestion des exceptions perso


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Avril 2012
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Avril 2012
    Messages : 21
    Par défaut Gestion des exceptions perso
    Bonjour,

    Aujourd'hui je m'intéresse aux exceptions personnalisé pour un projet, ayant des erreurs MySQL car certains champs
    sont en unique par exemple, je souhaite donc intercepté le code d'erreur, modifier le message et afficher
    le message d'erreur, le soucis c'est que ma classe d'exception perso est totalement zapé, comme si elle existait pas
    et je me retrouve avec le message d'origine.

    Voici ma connexion :
    Code : 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
     
    <?php
    function connect_bdd()
        {
            try 
            {
                $bdd = new PDO('mysql:host='.BDD_Host.';dbname='.$_SESSION["Bdd"], BDD_User, BDD_Pass);
                $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);            
     
                return $bdd;
            }
            catch(Exception $e) 
            {
                die('ERREUR PDO dans ' . $e->getFile() . ' L.' . $e->getLine() . ' : ' . $e->getMessage());
            }
        }
    ?>
    Ma class exception perso :
    Code : 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
     
    <?php 
    class customException extends Exception
        {
            public function __construct($message = NULL,$code = 0)
            {  
                parent::__construct($message, $code);
            }
     
            public function getMessageplus()
            {
                switch($this->code)
                {
                    case 23000 :
                        $message = "Il existe déjà un enregistrement dans la base de données, veuillez choisir d'autres valeurs.";
                        break;
                    default :
                        $message = $this->message;
                        break;
                }
     
                return $message;
            }
        }
    ?>
    L'appel de mes classes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <?php
        /**************************************/
        /* Chargement automatique des classes */
        /**************************************/
            set_include_path(Classes_Repertoire);
            spl_autoload_register();
        /**************************************/
    ?>
    Mon algorithme :
    Code : 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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    <?php
    try
                        {
                            $utilisateur = new utilisateur($_POST["Identifiant"],$_POST["Motdepasse"],$_POST["Confmotdepasse"]);
     
                            $bdd->beginTransaction();
     
                            $req = $bdd->prepare(ajout_utilisateur());
     
                            $req->bindValue(':Identifiant', $utilisateur->identifiant);
                            $req->bindValue(':Motdepasse', $utilisateur->getmotdepasse());
                            $req->bindValue(':SDA', Id_null($_POST["NumSDA"]));
     
                            if(!$req->execute())
                                $bdd->rollBack();
                            else
                            {
                                $IdUtilisateur = $bdd->lastInsertId();
     
                                $req = $bdd_admin->prepare(ajout_utilisateur_admin());
     
                                $req->bindValue(':IdUti', $IdUtilisateur);
                                $req->bindValue(':Identifiant', $utilisateur->getidentifiantbdd());
                                $req->bindValue(':IdBdd', $_SESSION["IdBdd"]);
     
                                if(!$req->execute())
                                    $bdd->rollBack();
                                else
                                {
                                    foreach($_POST["droitsUtilisateur"] as $droits)
                                    {
                                        $req = $bdd->prepare(ajout_droits_utilisateur());
     
                                        $req->bindValue(':IdUtilisateur', $IdUtilisateur);
                                        $req->bindValue(':IdNavigation', $droits);
     
                                        if(!$req->execute())
                                        {
                                            $bdd->rollBack();
                                            break;
                                        }
                                    }
                                }
                            }
     
                            $bdd->commit();
     
                            unset($utilisateur);
     
                            header ("Location: index.php?page=utilisateur");
                        }
                        catch(customException $e)
                        {
                            error_page($e->getMessageplus());
                        }
                        catch(Exception $e)
                        {
                                error_page($e->getMessage());
                        }
    ?>
    Je cherche depuis hier, j'ai lu toute la doc possible, même ici, j'ai rien trouver de plus, surtout que c'est basique =/et j'ai même un bouquin sur PHP5 a côté de moi et rien a faire ! je comprends pas ...


    Quelqu'un saurait il m'aider ? Merci d'avance.

  2. #2
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    Salut

    Il ne faut pas utiliser Exception mais PDOException car PDO intègre sa propre classe d'Exception (un dérivé de Exception d'ailleurs).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class customException extends Exception
    C'est très bien d'avoir sa propre classe d'Exception, ne serait-ce que pour toutes les erreur générales.

    Mais PDO c'est particulier du fait qu'il y a une classe PDOException pour ça.
    Donc si on souhaite gérer cela encore autrement (à sa façon), alors il faudrait créer une autre classe encore dérivée de PDOException.

    Ensuite déclencher cette nouvelle classe à la place, genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // customException.php (par exemple pour toutes le erreurs en général)
    // classe étendue de Exception
    class customException extends Exception {
     
    }
     
    // customPDOException.php (par exemple pour toutes le erreurs de PDO)
    //classe étendue de PDOException
    class customPDOException extends PDOException {
     
    }
    Puis pour PDO :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    function connect_bdd()
    {
        try 
        {
            $bdd = new PDO('mysql:host='.BDD_Host.';dbname='.$_SESSION["Bdd"], BDD_User, BDD_Pass);
            $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);            
     
            return $bdd;
        }
        catch(PDOException $e) 
        {
            die('ERREUR PDO dans ' . $e->getFile() . ' L.' . $e->getLine() . ' : ' . $e->getMessage());
        }
    }
    Cependant, si tu prévois d'attraper une erreur (peu importe le genre d'erreur), il faut lancer un exception soit même (throw new ...) si au moment de l'erreur PDO ne le fait pas.
    Ensuite, il faut faire en sorte que cette erreur qu'on provoque (soit même) puisse être attrapée au bon moment.
    Les 2 vont de paires.

    Dans ton exemple de code il faudrait faire un throw new customPDOException(), donc déclencher ta propre erreur d'exception.
    Puis tenter de l'attraper (en amont).

    Exemple (simple) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    try () {
        // du code
        if (une_erreur) {
            // rollback()
            throw new customPDOException('Ma propre erreur ...');
        }
        // du code
    }
    catch(customPDOException $e) {
        // On gère avec customPDOException
    }
    catch(PDOException $e) {
        // PDOException au cas où
    }

    Tout cela saut erreur, et à voir.

  3. #3
    Membre averti
    Inscrit en
    Avril 2012
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Avril 2012
    Messages : 21
    Par défaut
    C'est ce que j'allais dire les erreurs MySQL lève des erreurs sur la classe PDOException ou Exception
    je ne saurais dire et donc il n'est pas possible de redéfinir la classe qui gère les exceptions SQL par défaut,
    ni de modifier l'appel de la classe d'exception qui est appeler lorsque MySQL retourne une erreur.

    Pour résoudre le problème, il suffit de crée une fonction PHP qui recupère le code et le message,
    dans des conditions ont vérifie le code d'erreur et si celui ci correspond, on change le message puis on le retourne.

    Question de logique ...

    J'ai donc fait ceci :
    Code : 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
     
    <?php 
     
    catch(Exception $e)
                        {
                            error_page(customExceptionSQL($e->getCode(),$e->getMessage()));
                        }
     
    function customExceptionSQL($code,$message)
        {
            switch($code)
            {
                case 23000 :
                    $message = "Il existe déjà un enregistrement avec ses valeurs dans la base de données, veuillez choisir d'autres données.";
                    break;
            }
     
            return $message;
        }
     
    ?>

  4. #4
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    Pourquoi pas faire comme tu le fais, mais tu n'exploite pas vraiment la gestion des Erreurs et Exceptions telle elle est prévue.
    Rien que le faire avec des fonctions (mode procédural et non Objet) tu risques de passer à coté du principal but.
    Mais pourquoi pas encore une fois.

    les erreurs MySQL lève des erreurs sur la classe PDOException ou Exception
    je ne saurais dire et donc il n'est pas possible de redéfinir la classe qui gère les exceptions SQL par défaut,
    ni de modifier l'appel de la classe d'exception qui est appeler lorsque MySQL retourne une erreur.
    Dans ton code tu catch (attrape) l'erreur avec Exception, or, je viens de dire que PDO à sa propre classe : PDOException.
    Avec Exception tu prends le risque que le message soit moins pertinent qu'avec PDOException.
    Ce n'est pas pour rien que PDO à créé sa propre classe.

    Si tu veux que lors d'une erreur que ce soit ta propre classe d'Exception qui soit lancée au lieu de celle par défaut (PDOException) il suffit d'attraper l'exception et renvoyer la sienne à la place.
    Je ne vois pas où est le problème, c'est l'exemple que j'ai mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <?php
    try {
        // un code SQL en erreur
    }
    catch (PDOExeption $e) {
        throw new MyPDOException($e);
    }
    ?>
    On effectue un simple renvoie sur notre propre classe MyPDOException() pour la gérer comme on veut.
    Comme par exemple récupérer le code d'erreur pour décrire l'erreur à notre façon.

    Et l'autre principal intérêt d'avoir sa propre classe d'Exception c'est de pouvoir soit même déclencher des Exceptions (MyPDOException ou Exception, ou encore DiversException) selon la nature de l'erreur détectée.

    Donc dans la partie du rollback() par exemple, et admettons qu'on détecte une éventuelle incohérence qu'il peu avoir si on effectue la requête, on peu lancer sa propre Exception avec pourquoi son propre code d'erreur.
    Bref ... on peu envisager plein de scénarios.

  5. #5
    Membre averti
    Inscrit en
    Avril 2012
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Avril 2012
    Messages : 21
    Par défaut
    Citation Envoyé par RunCodePhp Voir le message
    Dans ton code tu catch (attrape) l'erreur avec Exception, or, je viens de dire que PDO à sa propre classe : PDOException.
    Avec Exception tu prends le risque que le message soit moins pertinent qu'avec PDOException.
    Ce n'est pas pour rien que PDO à créé sa propre classe.
    - J'ai pas fait spécialement gaffe
    - J'avais déjà essayer avec PDOException et le message était exactement le même ...

    Et dans tous les cas, même ta méthode n'est pas celle appropriée car ce n'est pas ainsi qu'on gère les exceptions personnalisé normalement.

    C'est cela que je voulais dire, c'est que la méthode correct n'est pas applicable dans se cas présent malheureusement, après le Full objet n'est qu'un idéal de vision sur la conception d'une application.
    Mais je reconnais que ton idée est valable et tout a fait correct ! Enfin bref, je pense que l'on peut dire que pour réaliser se travail, seul la "bidouille" est possible.

    Après si je voulais faire cela s'était avant tous pour cacher un champ unique qui enregistrait le hash, donc si un enregistrement existait, j'avais en message d'erreur le hash qui était déjà existant ... pas top pour la sécu, je souhaitais uniquement avoir cette classe pour modifier les messages d'erreurs SQL

  6. #6
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    Là tu m'étonnes

    Tout l'art d'une bonne gestion des Exceptions c'est de lancer des Exceptions pour ensuite les attraper afin de les gérer.
    Les 2 vont de paire.
    Rien de tel que la POO pour cela.

    C'est ce que fait PDO.
    Si PDO ne lançais aucune Exception (PDOException) tu n'aurais même pas ce code d'erreur que tu obtiens actuellement.

    Tout est là, faut juste adhérer au principe.
    Le faire de manière procédurale pour ma part c'est tout simplement ingérable.
    A part faire de la bidouille, c'est tout ce qu'on peu faire.


    Si on prend ton code, tu serais (à mon sens) au courant de cette erreur peut être trop tardivement, pas au bon moment.
    Si on veut gérer cette erreur convenable il suffit de la détecter pile (poil) là où elle a lieu et la gérer à ce moment.

    Ceci peu certes déboucher sur une sur-couche de code, comme étendre la classe PDO, voir aussi PDOStatement, etc ... pour pouvoir déclencher une Exception pour ensuite l'attraper tout de suite après.


    En tout cas le try/catch dans ton code est fait sur un gros bloc de code.
    Il peu avoir une grande quantité d'erreurs possibles et en tout genre, dans ce cas là il est normal d'avoir quelque difficulté à gérer une certaine erreur finement.

Discussions similaires

  1. [ADOConnect] gestion des exception en tout temps
    Par portu dans le forum Bases de données
    Réponses: 1
    Dernier message: 20/04/2005, 20h01
  2. [ORACLE 9i] Gestion des exceptions
    Par sygale dans le forum SQL
    Réponses: 6
    Dernier message: 19/08/2004, 16h06
  3. Gestion des exception (EOleException)
    Par shurized dans le forum Bases de données
    Réponses: 5
    Dernier message: 30/06/2004, 18h25
  4. [XMLRAD] gestion des exceptions
    Par pram dans le forum XMLRAD
    Réponses: 2
    Dernier message: 28/01/2003, 18h48
  5. c: gestion des exceptions
    Par vince_lille dans le forum C
    Réponses: 7
    Dernier message: 05/06/2002, 15h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo