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 :

[POO] Gestion des Singleton


Sujet :

Langage PHP

  1. #1
    Modérateur
    Avatar de Bisûnûrs
    Profil pro
    Développeur Web
    Inscrit en
    Janvier 2004
    Messages
    9 868
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2004
    Messages : 9 868
    Points : 16 258
    Points
    16 258
    Par défaut [POO] Gestion des Singleton
    Salut,

    J'aurais aimé avoir votre avis sur une classe gérant les Singleton de toutes les autres classes. Voici la classe en question :

    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
    class EtatClasse
    {
     
       function verifInstanceClasse( $class, $toConstruct = array() )
       {
          if ( !ETATCLASSE::dejaInstantiee( $class ) )
          {
             $GLOBALS['_' . strtoupper( $class ) . '_INSTANTIEE']   = true;
             eval( '$GLOBALS["_' . strtoupper( $class ) . '_OBJET"] = new ' . $class . '("' . implode( '", "', $toConstruct ) . '");' );
          }
       }
     
       function dejaInstantiee( $class )
       {
          return $GLOBALS['_' . strtoupper( $class ) . '_INSTANTIEE'];
       }
     
    }
    Est-ce que l'utilisation d'eval() est judicieuse ? Ne prendra-t-elle pas trop de ressources ?

    Un exemple d'utilisation de cette classe est par exemple plusieurs appels à une classe de webservices sur la même page :

    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
    class WebService
    {
     
       function __construct( $url )
       {
          $this->WebServiceClient = new SoapClient( $url );
       }
     
       function call( $set )
       {
          // Traitement
       }
     
    }
     
    function webService( $set )
    {
       if ( !isset( $set['url'] ) )
       {
          $set['url'] = WEBSERVICE_URL;
       }
     
       ETATCLASSE::verifInstanceClasse( __FUNCTION__, array( $set['url'] ) );
     
       return $GLOBALS['_WEBSERVICE_OBJET']->call( $set );
    }
     
    $maVar = webService(
                array (
                  'fonction'  => 'maFonctionWS',
                  'params'    => ''
                )
             );
    Donc pour résumer, j'ai une fonction du même nom que la classe que je veux "singletoniser". Cette fonction fait l'appel à la classe "singletonisatrice" qui instancie la classe si elle ne l'est pas déjà.

    Que pensez-vous de cette méthode ?

    Si vous avez des questions ou des améliorations à proposer, je suis tout ouïe !


  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 448
    Points : 2 284
    Points
    2 284
    Par défaut
    Mitigé. Si c'est dans l'optique de s'en servir dans tous les contexte, je préfère utiliser un singleton naturel.
    Maintenant dans certain cas particulier cela peut surement être util.
    Cependant je remplacerait effectivement eval par un call_user_func* ou un coup de reflexion.

    Et puis au départ je pensais que c'était pour php4

    bye

  3. #3
    Modérateur
    Avatar de Bisûnûrs
    Profil pro
    Développeur Web
    Inscrit en
    Janvier 2004
    Messages
    9 868
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2004
    Messages : 9 868
    Points : 16 258
    Points
    16 258
    Par défaut
    L'intérêt de ce développement était de ne pas toucher aux scripts appelant les fonctions déjà en place (ici, la fonction webService développée de manière procédurale il y a quelques mois) et donc ne modifier que le coeur de la fonction pour qu'elle fasse appel à la classe webService nouvellement créée.

    Le problème avec call_user_func_array est que je ne peux pas appeler le constructeur de ma classe, celui-ci ne pouvant être appelé de manière statique ..

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 448
    Points : 2 284
    Points
    2 284
    Par défaut
    Jettes un œil sur l'exemple de la doc

    http://fr.php.net/manual/fr/language...eflectionclass

  5. #5
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 235
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 235
    Points : 15 532
    Points
    15 532
    Par défaut
    déjà sans regarder ce que fait la classe, j'ai l'habitude de dire que l'utilisation de GLOBALS et de "eval" n'est pas conseillé pour la POO

    ensuite à la place de GLOBALS je te proposerai de stocker le tableau dans un attribut statique de la classe mais par contre si tu tiens absolument à passer la liste "toConstruct" sous cette forme, je ne vois pas comment éviter "eval"

    edit : voilà comment je verrai la chose :
    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
     
    class EtatClasse
    {
        public static function obtientSingleton($classe, $toConstruct = array())
        {
            if (!isset(self::$tableauSingleton)) {
                self::$tableauSingleton = array();
            }
     
            if (!isset(self::$tableauSingleton[$classe])) {
                $listeArguments = implode('", "', $toConstruct);
     
                eval("self::\$tableauSingleton[\$classe] = new $classe(\"$listeArguments\");");
            }
     
            return self::$tableauSingleton[$classe];
        }
     
        private static $tableauSingleton;
    }
     
    class Test
    {
        public function __construct($nombre)
        {
            $this->nombre = $nombre;
        }
     
        public function affiche()
        {
            echo "coucou {$this->nombre}\n";
        }
     
        private $nombre;
    }
     
    EtatClasse::obtientSingleton('Test', array(1))->affiche();
    EtatClasse::obtientSingleton('Test', array(2))->affiche();
    edit 2 :
    Citation Envoyé par kaymak Voir le message
    Jettes un œil sur l'exemple de la doc

    http://fr.php.net/manual/fr/language...eflectionclass
    oh je viens de comprendre pourquoi tu parlais de ça, ça permet de faire disparaitre le "eval" et de mettre ça à la place :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            if (!isset(self::$tableauSingleton[$classe])) {
                $class = new ReflectionClass($classe);
                self::$tableauSingleton[$classe] = call_user_func_array(array($class, 'newInstance'), $toConstruct);
            }
    ça tombe bien parce qu'avec la solution avec "eval", tu dois rajouter les cas où les arguments sont vides ou des objets ou bien si l'argument contient un "

  6. #6
    Modérateur
    Avatar de Bisûnûrs
    Profil pro
    Développeur Web
    Inscrit en
    Janvier 2004
    Messages
    9 868
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2004
    Messages : 9 868
    Points : 16 258
    Points
    16 258
    Par défaut
    En suivant vos conseils, je suis arrivé à 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
    class EtatClasse
    {
        private static $tableauSingleton;
     
        public static function obtientSingleton($classe, $toConstruct = array())
        {
            if (!isset(self::$tableauSingleton)) {
                self::$tableauSingleton = array();
            }
     
            if (!isset(self::$tableauSingleton[$classe])) {
                $reflectionClass = new ReflectionClass( $classe );
                self::$tableauSingleton[$classe] = $reflectionClass->newInstanceArgs( $toConstruct );
            }
     
            return self::$tableauSingleton[$classe];
        }
    }
    La classe reflectionClass a une méthode qui permet de se passer de call_user_func_array. Il ne faut pas utiliser newInstance mais newInstanceArgs pour passer un tableau d'arguments (à l'instar de respectivement call_user_func et call_user_func_array).

    Et l'appel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function webService( $set )
    {
       if ( !isset( $set['url'] ) ) {
          $set['url'] = WEBSERVICE_URL;
       }
     
       $ws = ETATCLASSE::obtientSingleton( __FUNCTION__, array( $set['url'] ) );
     
       return $ws->call( $set );
    }
    Merci beaucoup à vous deux !

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

Discussions similaires

  1. [POO] gestion des exceptions
    Par maysa dans le forum Langage
    Réponses: 10
    Dernier message: 21/04/2009, 14h08
  2. [POO] Gestions des événements en javascript
    Par magalieParis13 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 27/11/2008, 17h47
  3. [POO] Gestion des exception avec php4
    Par mulot49 dans le forum Langage
    Réponses: 1
    Dernier message: 26/04/2007, 10h18
  4. [POO] PHP et la gestion des classes
    Par Acti dans le forum Langage
    Réponses: 7
    Dernier message: 23/09/2005, 00h06

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