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 :

php design pattern chaine de responsabilités


Sujet :

Langage PHP

  1. #1
    Membre chevronné

    Homme Profil pro
    développeur
    Inscrit en
    Octobre 2013
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : développeur

    Informations forums :
    Inscription : Octobre 2013
    Messages : 1 576
    Points : 1 989
    Points
    1 989
    Par défaut php design pattern chaine de responsabilités
    Bonjour à tous,

    J'aurais besoin de votre aide s'il vous plaît?

    J’essaie d'implémenter le design pattern chaine de responsabilité pour créer un filtre de simple si la valeur est une chaine on la mets en majuscule sinon on renvoie le double.
    Cela fonctionne ma question est que je n'utilise pas le typeint de php7 justement pour pouvoir filtrer sur la bonne classe, comment feriez vous? Mon code peut-être améliorer, avez vous des conseils?

    Class abstraite
    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
    <?php
     
    namespace Exercises\ChainResponsabilityPattern\Complete;
     
    abstract class MainFilterAbstract 
    {
      /**
       * @var MainFilterAbstract|null
       */
      protected $_successor = null;
     
      public function __construct(MainFilterAbstract $successor = null)
      {
          $this->_successor = $successor;
      }
     
      abstract public function filter();
    }
    le filtre pour les majuscules
    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
     
    namespace Exercises\ChainResponsabilityPattern\Complete;
     
    class UpperCaseFilter extends MainFilterAbstract
    {
        public function __construct(MainFilterAbstract $filter = null)
        {
            parent::__construct($filter);
        }
     
       public function filter($content = null)
       {
           if(is_string($content))
           {
               return strtoupper($content);
           }
     
           return $this->_successor->filter($content);
       }
    }
    Pour le double
    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
    <?php
     
    namespace Exercises\ChainResponsabilityPattern\Complete;
     
    class DoubleFilter extends MainFilterAbstract 
    {
        public function __construct(MainFilterAbstract $filter = null)
        {
            parent::__construct($filter);      
        }
     
        public function filter($content = null)
        {
           if(is_int($content))
           {
               return $content * 2;
           }
     
           return $this->_successor->filter($content);
        }
     
    }
    le fichier d'execution
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $upperCaseFilter = new UpperCaseFilter();
    $myFilter = new DoubleFilter($upperCaseFilter);
     
    $space = ' ';
     
    echo $myFilter->filter('hello') . $space;
    echo $myFilter->filter('24') . $space;
    echo $myFilter->filter(360) . $space;
    La sortie console
    Merci

  2. #2
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Points : 16 372
    Points
    16 372
    Par défaut
    Si je comprends bien, ton problème est le cas à la limite où tu reçois un nombre sous forme de chaine. Dans ce cas, tu veux le traiter comme un nombre et non pas comme une chaine. C'est bien ça ?

    Tu peux essayer d'utiliser is_​numeric (mais ça ne distingue pas entre entier et décimal) et/ou filter_​var avec le filtre FILTER_VALIDATE_INT.

    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
    class UpperCaseFilter extends MainFilterAbstract
    {
       public function filter($content = null)
       {
           if(is_string($content) && !is_numeric($content))
           {
               return strtoupper($content);
           }
     
           return $this->_successor->filter($content);
       }
    }
     
    class DoubleFilter extends MainFilterAbstract 
    {
        public function filter($content = null)
        {
           $contentFiltre = filter_var($content, FILTER_VALIDATE_INT);
           if($contentFiltre !== false) // attention au !==, le nombre peut être égal à 0
           {
               return $contentFiltre * 2;
           }
           return $this->_successor->filter($content);
        }
     
    }
    Remarque annexe : attention, si un de tes éléments n'a pas de successeur, ça va t'exploser à la figure. Je pense que tu devrais avoir une méthode filtrer() générique au niveau de l'abstract et une méthode abstraite à implémenter qui fait le filtrage proprement dit. 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
    abstract class MainFilterAbstract 
    {
        /**
        * @var MainFilterAbstract|null
        */
        protected $_successor = null;
     
        public function __construct(MainFilterAbstract $successor = null)
        {
            $this->_successor = $successor;
        }
     
        public final function filter($content) {
            // On fait le filtre
            $result = $this->doFilter($content);
            // Si on a un successeur, on l'appelle
            if ($this->_successor) {
                $result = $this->_successor->filter($result);
            }
            return $result;
        }
     
        abstract protected function doFilter();
    }
    EDIT : la méthode filter doit être final histoire d'éviter qu'on la surcharge par erreur
    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]

  3. #3
    Membre chevronné

    Homme Profil pro
    développeur
    Inscrit en
    Octobre 2013
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : développeur

    Informations forums :
    Inscription : Octobre 2013
    Messages : 1 576
    Points : 1 989
    Points
    1 989
    Par défaut
    Merci Celira,

    J'ai un problème de successeur null pour les valeurs entières

    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
    <?php
     
    namespace Exercises\ChainResponsabilityPattern\Complete;
     
    abstract class MainFilterAbstract 
    {
      /**
       * @var MainFilterAbstract|null
       */
      protected $_successor = null;
     
      /**
       * constructor
       *
       * @param MainFilterAbstract $successor
       */
      public function __construct(MainFilterAbstract $successor = null)
      {
          $this->_successor = $successor;
      }
     
      /**
       * filter $content 
       *
       * @param [string|int] $content
       * @return string|int
       */
      public function filter($content)
      {
     
        $result = $this->doFilter($content);
        var_dump($this->_successor);
        if ($this->_successor) { 
            $result = $this->_successor->filter($result);
        }
     
        return $result;
      }
     
      abstract public function doFilter();
    }
    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
    NULL
    object(Exercises\ChainResponsabilityPattern\Complete\UpperCaseFilter)#3 (1) {
      ["_successor":protected]=>
      NULL
    }
    NULL
    HELLO object(Exercises\ChainResponsabilityPattern\Complete\UpperCaseFilter)#3 (1) {
      ["_successor":protected]=>
      NULL
    }
    PHP Fatal error:  Uncaught Error: Call to a member function filter() on null in /home/kevin/php-interview-exercises/exercises/ChainResponsabilityPattern/Complete/UpperCaseFilter.php:19
    Stack trace:
    #0 /home/kevin/php-interview-exercises/exercises/ChainResponsabilityPattern/Complete/MainFilterAbstract.php(31): Exercises\ChainResponsabilityPattern\Complete\UpperCaseFilter->doFilter(48)
    #1 /home/kevin/php-interview-exercises/exercises/ChainResponsabilityPattern/Complete/MainFilterAbstract.php(34): Exercises\ChainResponsabilityPattern\Complete\MainFilterAbstract->filter(48)
    #2 /home/kevin/php-interview-exercises/exercises/ChainResponsabilityPattern/exercice.php(30): Exercises\ChainResponsabilityPattern\Complete\MainFilterAbstract->filter('24')
    #3 {main}
      thrown in /home/kevin/php-interview-exercises/exercises/ChainResponsabilityPattern/Complete/UpperCaseFilter.php on line 19

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $upperCaseFilter = new UpperCaseFilter();
    $myFilter = new DoubleFilter($upperCaseFilter);
     
    $space = ' ';
     
    echo $myFilter->filter('hello') . $space;
    echo $myFilter->filter('24') . $space; 
    echo $myFilter->filter(360) . $space;
    Le problème vient de '24' car le successeur est null, je recupère bien 48 mais si je fais ===null ou ===NULL dans le if même problème
    Merci

  4. #4
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Points : 16 372
    Points
    16 372
    Par défaut
    Autant (*) pour moi : il faut adapter les enfants en fonction du parent, sinon ça sert à rien : on implémente la méthode abstraite et on ne touche surtout pas à la méthode public. Par exemple :

    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
    namespace Exercises\ChainResponsabilityPattern\Complete;
     
    class UpperCaseFilter extends MainFilterAbstract
    {
     
       protected function doFilter($content = null)
       {
           if(is_string($content))
           {
               return strtoupper($content);
           }
     
           return $content;
       }
    }
    (*) ou au temps, je sais jamais et c'est pas important
    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]

  5. #5
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 691
    Points : 20 222
    Points
    20 222
    Par défaut
    D'un point vue purement conceptuel je définirais le successeur via un setter dédié et non via le constructeur.
    Ça permet entre autre de pouvoir utiliser un des éléments de ta chaîne en toute indépendance sans définir aucun successeur.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre chevronné

    Homme Profil pro
    développeur
    Inscrit en
    Octobre 2013
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : développeur

    Informations forums :
    Inscription : Octobre 2013
    Messages : 1 576
    Points : 1 989
    Points
    1 989
    Par défaut
    Super merci Celira ça fonctionne,

    D'un point vue purement conceptuel je définirais le successeur via un setter dédié et non via le constructeur.
    Ça permet entre autre de pouvoir utiliser un des éléments de ta chaîne en toute indépendance sans définir aucun successeur.
    Merci
    J'ai fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $upperCaseFilter = new UpperCaseFilter();
    $myFilter = new DoubleFilter();
    $myFilter->setSuccessor($upperCaseFilter);
     
    $space = ' ';
     
    echo $myFilter->filter('hello') . $space;
    echo $myFilter->filter('24') . $space;
    echo $myFilter->filter(360) . $space;
    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
    <?php
     
    namespace Exercises\ChainResponsabilityPattern\Complete;
     
    abstract class MainFilterAbstract 
    {
      /**
       * @var MainFilterAbstract|null
       */
      protected $_successor = null;
     
      /**
       * getter $_successor
       *
       * @return MainFilterAbstract
       */
      public function getSuccessor() : MainFilterAbstract
      {
         return $this->_successor;
      }
     
      /**
       * setter $_successor
       *
       * @param MainFilterAbstract $succesor
       * @return void
       */
      public function setSuccessor(MainFilterAbstract $succesor = null)
      {
         $this->_successor = $succesor;
      }
     
      /**
       * filter $content 
       *
       * @param [string|int] $content
       * @return string|int
       */
      public function filter($content)
      {
     
        $result = $this->doFilter($content);
     
        if ($this->_successor) { 
            $result = $this->_successor->filter($result);
        }
     
        return $result;
      }
     
      abstract public function doFilter();
    }
    Par contre je n'ai pas compris l'utilité par rapport au constructeur

  7. #7
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 691
    Points : 20 222
    Points
    20 222
    Par défaut
    J'avais pas vu que dans ton constructeur tu définissais le successeur à null par défaut , donc effectivement pas de différence avec un setter.
    Ceci étant dit je préfère passer par un setter. Quelqu'un qui reprend ton code qui veux juste filtrer un double par exemple va devoir se poser la question de ce paramètre dans le constructeur. est ce que je dois le définir , que se passe t'il si je le laisse à null , etc ... Avec un setter c'est plus transparent.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. Livre sur les Designs patterns pour PHP
    Par thewind1 dans le forum Design Patterns
    Réponses: 1
    Dernier message: 04/07/2008, 08h28
  2. [Chaîne de responsabilités] Design pattern chaine de responsabilité
    Par Luffy_San dans le forum Design Patterns
    Réponses: 3
    Dernier message: 13/02/2008, 08h49

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