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 :

try-catch dans un constructeur [POO]


Sujet :

Langage PHP

  1. #1
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 830
    Points
    5 830
    Billets dans le blog
    1
    Par défaut try-catch dans un constructeur
    Bonjour,

    je souhaite contrôler le type des arguments passés au constructeur de ma classe . Pour éviter un message d'erreur si l'utilisateur met des paramètres d'un type non accepté, je pensais mettre un try-catch. Mais ça me génère un message d'erreur. Pourquoi ?

    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
     
    <?php
    declare(strict_types=1);
    namespace Classes\Olivier;
     
    class Country
    {
      // no setter as the constructor is sufficient
        private $name;  //string
        private $region;  //string 
     
          /* Constructor
          */
        public function __construct(string $name, string $region='') //the 2nd parameter is optional
        {
          try {
            $this->name=$name;
            $this->region=$region;
          }
          catch {
            echo "format incorrect<br/>";
          }
        }

    Parse error: syntax error, unexpected '{', expecting '(' in C:\wamp64\www\ticket2\Classes\Olivier\Country.php on line 20
    Je suis en PHP7.3.5

  2. #2
    Invité
    Invité(e)

  3. #3
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,
    Citation Envoyé par laurentSc Voir le message
    Pour éviter un message d'erreur si l'utilisateur met des paramètres d'un type non accepté
    si le typage des variables te pose un problème, je ne vois pas pourquoi tu ne le retires pas ?
    D'ailleurs, je ne comprends pas trop ton problème et personnellement je ne retirerais pas le typage

    Pour ton apprentissage :
    Un constructeur doit éviter autant que possible de tirer des exceptions.
    S'il le fait, c'est l'instanciation de la classe qui doit être encapsulée au sein d'un bloc try ... catch ... externe.
    Un constructeur ne peut avoir de return sauf un return (void).

    Dis-moi, tu as avancé sur la POO pendant ton sommeil que tu sois confronté aujourd'hui à ce genre de problématique complexe ?
    Ce genre de problème ne se présente que quand tu fais de l'architecture avancée.

  4. #4
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 830
    Points
    5 830
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    je ne suis dispo pour vous répondre que maintenant.

    Déjà merci à Jérôme car bien que je sache qu'on peut faire des try-catch, je l'avais encore jamais fait...

    Ce que je voudrais, c'est imposer le type des variables (d'où le declare(strict_types=1);), et que si l'utilisateur essaye d'instancier la classe en passant des variables d'un mauvais type, ça affiche un message d'erreur mais ne plante pas le script.

    Je m'attendais à un message d'erreur avec ce code :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    try{
       $country1=new Country(33); echo "country:". $country1."<br/>";
    }
    catch (Exception $e){
        echo "format incorrect<br/>";
      }

    country.php :
    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
     
    <?php
    declare(strict_types=1);
    namespace Classes\Olivier;
     
    class Country
    {
      // no setter as the constructor is sufficient
        private $name;  //string
        private $region;  //string 
     
          /* Constructor
          */
        public function __construct(string $name, string $region='') //the 2nd parameter is optional
        {
            $this->name=$name;
            $this->region=$region;
            echo "type=".gettype($name)."<br/>";
        }
    ...
    mais non, et le type affiché est string et non int. Pourquoi ?

  5. #5
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,

    t'as juste oublié la directive : declare(strict_types=1); au début du script contenant le try.
    Cette directive doit être OBLIGATOIREMENT présente sur tous les scripts pour que le moteur l'applique.

    Si tu l'ajoutes, voici ce que tu obtiens :
    Fatal error: Uncaught TypeError: Argument 1 passed to Classes\Olivier\Country::__construct() must be of the type string, int given, called in
    Et là, ça fonctionne comme attendu

  6. #6
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 830
    Points
    5 830
    Billets dans le blog
    1
    Par défaut
    Merci pour l'explication sauf que l'attendu, c'est pas une fatal error de PHP mais que le script détecte le mauvais type et affiche un message d'erreur et que le script ne plante pas...

  7. #7
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    le moteur détecte bien le mauvais type et il plante ce qui est tout à fait normal. C'est ce qui assure la cohérence d'une part et un niveau de sécurité accru d'autre-part.
    Cette rigidité oblige le développeur à une très grosse rigueur et c'est à lui de s'assurer que ce qu'il présente en entrée de fonction correspond parfaitement à ce qui est attendu.
    Le moteur ne fera pas ce travail à ta place : si les types ne correspondent pas : le jeu est terminé.
    Donc en amont, soit tu t'assures que les types de données collent parfaitement, soit tu les castes explicitement mais dans tous les cas, s'il y a un problème à posteriori, ça ne sera uniquement que de la faute du développeur.

    Bref, codage autrement plus propre et sécurisé.

  8. #8
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 830
    Points
    5 830
    Billets dans le blog
    1
    Par défaut
    OK. Il est clair que ce contrôle du type des arguments doit être placé en dehors de la classe, vu que sinon, il est trop tard pour exécuter ce contrôle vu que le moteur aura déjà planté.

    Voici le code que j'imagine avant d'instancier la classe. Est-ce correct ?

    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
     
    function ctrl_type_arguments($arg,$typ_arg)
    {
        foreach($arg as $key=>$argum)
        {
            if (gettype($argum) != $typ_arg[$key]) return(FALSE);
        }
        return(TRUE);
    }
     
    $arg=['33'];
    $typ_arg=['string'];
    foreach($arg as $argum)
    if (ctrl_type_arguments($arg,$typ_arg)) { $country1=new Country($argum); echo "country:". $country1."<br/>";}
    else echo "format incorrect<br/>";

  9. #9
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 830
    Points
    5 830
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    j'ai essayé d'améliorer le code pour contrôler le type. Je suis parti sur ce code :
    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
     
    function ctrl_type_arguments($argum)
    {
        if (gettype($argum['value']) != $argum['type']) return(FALSE);
        else return(TRUE);
    }
     
    $arg = [
        ['value' => 'france', 'type' => 'string'], 
        ['value' => 'ISMA', 'type' => 'string']
    ];
     
    foreach($arg as $argum)
        if (ctrl_type_arguments($argum)) $OK=TRUE;
        else { $OK=FALSE; echo "format incorrect :".$argum['value']."<br/>"; }
    Ca fait plus clean, mais je suis incapable de le compléter. Mon idée est-elle bonne ? Et comment la compléter ?

  10. #10
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    salut,

    je ne comprends pas trop ton problème.
    dans le processus de traitement, à un moment tu t'assures bien de ce que tu manipules, non ? Donc au pire tu n'as qu'à caster les valeurs au moment où tu fais appel à la fonction.

    Tiens, voici comment je procède d'une manière imagée :
    quand une valeur externe arrive dans l'application, je lui fournis une armure qui lui permet de voyager dans toutes les parties de mon framework sans aucune dangerosité. Cette armure fournit également un collecteur d'erreurs, ce qui à chaque étape permet à l'application de lui raccrocher les erreurs spécifiques à cette valeur.
    Par ailleurs et dans un souci d'automatisation des processus de remontées d'erreurs à l'interface client, à chaque valeur est rattaché l'identifiant ou le nom du contrôle de l'interface graphique source de la valeur.

    En gros, toutes les valeurs sont des instances d'une classe MyVar :
    Quelque chose comme ça :
    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    <?php
     
    declare(strict_types=1);
     
    class MyVar
    {
        /**
         * Valeur saisie par l'utilisateur
         *
         * @var mixed
         */
        private $user_value;
        /**
         * html's name de l'interface graphique utilisé pour le suivi automatique des messages d'erreur
         *
         * @var string
         */
        private $gui_name = null;
        /**
         * Pour les valeur qui n'ont pas de contrôle spécifique dans un formulaire (type="hidden")
         * Texte à ajouter en début de message d'erreur
         *
         * @var array   [txt, translate => true, ph_values => []]
         */
        private $gui_text = [];
        /**
         * @var EECollector Erreurs et exceptions
         */
        private $eec;
     
        /**
         * @param mixed  $value
         * @param string $gui_name html's name dans l'interface graphique
         * @param array  $gui_text Texte à ajouter en début de message d'erreur [txt, translate => bool, ph_values => []]
         */
        public function __construct($value = null, ?string $gui_name = null, array $gui_text = [])
        {
            $this->user_value = $value;
            $this->gui_name   = $gui_name;
            $this->gui_text   = $gui_text;
            $this->eec        = new EECollector();
        }
     
        /**
         * Renvoie le collecteur d'erreurs et d'exceptions
         *
         * @return EECollector
         */
        public function eec(): EECollector
        {
            return $this->eec;
        }
     
        /**
         * @return mixed
         */
        public function userValue()
        {
            return $this->user_value;
        }
     
        /**
         * Définit l'identifiant de l'interface graphique auquel est rattachée la variable
         *
         * @param  string $p
         * @return MyVar
         */
        public function setGuiName(string $p): self
        {
            $this->gui_name = $p;
            return $this;
        }
     
        /**
         * Renvoie l'identifiant de l'interface graphique auquel est rattachée la variable
         *
         * @return string|null
         */
        public function guiName(): ?string
        {
            return $this->gui_name;
        }
     
        /**
         * Texte à ajouter en début de message d'erreur
         * Si translate alors txt doit correspondre à un tuid du dictionnaire
         *
         * @param  array $p  [txt => string (tuid), translate => bool, ph_values => []]
         * @return self
         */
        public function setGuiText(array $p): self
        {
            $this->gui_text = $p;
            return $this;
        }
     
        /**
         * Texte à ajouter en début de message d'erreur
         * Si translate alors txt doit correspondre à un tuid du dictionnaire
         *
         * @return array   [txt => string (tuid), translate => bool, ph_values => []]
         */
        public function guiText(): array
        {
            return $this->gui_text;
        }
     
        /**
         * Indique si la variable n'a aucune erreur rattachée
         *
         * @return bool
         */
        public function isOk(): bool
        {
            return $this->eec->isEmpty();
        }
     
        /**
         * Indique si des erreur ont été rattachées
         *
         * @return bool
         */
        public function isNotOk(): bool
        {
            return $this->eec->isNotEmpty();
        }
     
        /**
         * Indique si la valeur définie par l'utilisateur est un objet
         *
         * @return bool
         */
        public function isIofObject(): bool
        {
            return is_object($this->user_value);
        }
     
        /**
         * Indique si la valeur définie par l'utilisateur est de type Number
         *
         * @return bool
         */
        public function isIofNumber(): bool
        {
            return ($this->user_value instanceof Number);
        }
     
        /**
         * Indique si la valeur définie par l'utilisateur est de type Time
         *
         * @return bool
         */
        public function isIofTime(): bool
        {
            return ($this->user_value instanceof Time);
        }
     
        /**
         * Indique si la valeur définie par l'utilisateur est null
         *
         * @return bool
         */
        public function isNull(): bool
        {
            return ($this->user_value === null);
        }
     
        /**
         * Indique si la valeur définie par l'utilisateur est scalaire
         *
         * @return bool
         */
        public function isScalar(): bool
        {
            return is_scalar($this->user_value);
        }
     
        /**
         * Indique si la valeur définie par l'utilisateur est un tableau
         *
         * @return bool
         */
        public function isArray(): bool
        {
            return is_array($this->user_value);
        }
    }
    Et ensuite je fais et ne manipule que des instance de MyVar :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $nom = new MyVar($_POST['nom'] ?? '', 'nom');

  11. #11
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 830
    Points
    5 830
    Billets dans le blog
    1
    Par défaut
    Moi aussi, j'ai du mal à comprendre...

    dans le processus de traitement, à un moment tu t'assures bien de ce que tu manipules, non ? Donc au pire tu n'as qu'à caster les valeurs au moment où tu fais appel à la fonction.
    est-ce que tu veux dire que quand j'instancie la classe, je devrais déjà avoir contrôlé le type des arguments que je lui passe ?

    J'ai du mal à suivre ton image avec une armure. Pour essayer de comprendre, j'ai essayé ton code, mais il ne trouve pas la classe EECollector...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utilisation de try catch dans une procédure de backup de database
    Par megtrinity dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 05/11/2009, 14h53
  2. Try, catch dans une fonction
    Par mactwist69 dans le forum Windows Forms
    Réponses: 10
    Dernier message: 10/07/2008, 16h39
  3. Try/ catch dans une fonction ActionPerformed
    Par thomas2929 dans le forum Langage
    Réponses: 13
    Dernier message: 09/06/2008, 12h06
  4. Problème try-catch dans mon code
    Par little pepito dans le forum Langage
    Réponses: 7
    Dernier message: 11/06/2007, 12h22
  5. Try catch dans une dll - possible ?
    Par Pendary dans le forum C++Builder
    Réponses: 1
    Dernier message: 02/03/2007, 16h48

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