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

PHP & Base de données Discussion :

singleton pdo class ?


Sujet :

PHP & Base de données

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    378
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 378
    Points : 94
    Points
    94
    Par défaut singleton pdo class ?
    Bonjour, je suis à la recherche d'une classe SINGLETON autour de PDO
    j'en ai trouvé mais jamais complète

    avez-vous cela sous la main ou sur un site.

    car j'en trouve mais sans clone, sans construct, sans destruct...

    Et aussi sans try catch

    Donc au final je ne sais plus ce qu'il doit y avoir ou non afin d'être le plus prêt de la réalité

    Merci

  2. #2
    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
    car j'en trouve mais sans clone, sans construct, sans destruct
    Et ?

    Le clone va te servir à quoi ? Sur un singleton je vois pas bien
    Le construct est private sur un singleton donc bon ...
    Le destruct sert à rien si le code est fait correctement.

    Es tu certain de savoir ce qu'est un singleton et es tu sur d'en avoir besoin ?
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    • Le clone sur un singleton est une hérésie
    • Le constructeur d'un singleton est par définition caché
    • Le destructeur de la classe PDO ne ferme par explicitement la connexion donc il n'est pas utile


    Pour avoir fait des singletons pendant pas mal de temps je te garantis que ce n'est pas une solution, même dans le cas d'une connexion à la BDD.
    Selon moi, une classe de service qui prends en charge des instances uniques: oui, des singletons partout: non.

    Pourquoi ? Tout simplement parce que le singleton introduit un très fort couplage entre tes classes (par exemple, toutes les classes qui interrogent la base de donnée - tes classes modèles - seront extrêmement couplées au singleton de connexion) ce qui nuit gravement à la flexibilité de ton composant.

    Après à toi de voir

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    378
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 378
    Points : 94
    Points
    94
    Par défaut
    Merci de vos conseils car j'essaye de me mettre à la POO donc je bascule le code d'une petite appli en objet étape par étape.

    BENJAMIN > que me proposes tu comme exemple de classe de service

    voici le singleton qui semble fonctionner au niveau connexion par contre je n'arrive pas à lancer la fonction query

    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
     
    <?php
     
        define("SERVER","localhost");
        define('USER',"login");
        define('PASSWD',"pwd");
        define('DB_NAME', "base");
       define('PDO_DSN',"mysql:host=" . SERVER . ";dbname=" . DB_NAME);
     
    class sdb 
    {  
        static private $PDOInstance; 
     
        private function __construct($dsn, $username, $password) 
        {
            if(!self::$PDOInstance) { 
    	        try {
    			   self::$PDOInstance = new PDO($dsn, $username, $password);
    			  // self::$PDOInstance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    			} catch (PDOException $e) { 
    			   die("PDO ERREUR: " . $e->getMessage() . "<br/>");
    			}
        	}
          	return self::$PDOInstance;    	    	
        }
     
     
     
        public static  function getInstance($dsn, $username=false, $password=false)
     
        {
     
            if (is_null (self::$PDOInstance)) {
     
                self::$PDOInstance = new self($dsn, $username, $password);
     
            }
     
            return self::$PDOInstance;
     
        }
     
     
    }
     
    $db = sdb::getInstance(PDO_DSN,USER,PASSWD);
     
     
    foreach ($db->query("SELECT id,name FROM liste") as $row)
    {
        echo '<p>'.$row['name'].'</p>';
    }
    ?>
    j'obtiens le message d'erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Fatal error: Call to undefined method sdb::query() in /www/singleton_test.php on line 52
    Merci

  5. #5
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2007
    Messages
    748
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 748
    Points : 1 022
    Points
    1 022
    Par défaut
    salut , j'ai posté un morceau de classe que je cherche à compléter ( qu'il faudrait compléter... ) [dernier message]

    http://www.developpez.net/forums/d12...ents-francais/

    à voir avec les pros si c'est un bon départ, mais ça fonctionne
    Conception / Dev

  6. #6
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    Voici par exemple la classe de service principale dont je me sers dans Axiom: https://github.com/bdelespierre/php-...xiom.class.php
    De cette façon, seule la classe Axiom est un singleton, toutes les autres classes qui sont manipulées restent totalement flexibles.

    Dans ton code, la méthode query ne peut pas être appelée car elle ne fait pas partie de la classe sdb, tu dois soit la créer, soit utiliser __callStatic.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 75
    Points : 73
    Points
    73
    Par défaut
    Bonjour,

    J'utilise le singleton ci-dessous qui marche parfaitement :

    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
    class DB
    {
     
       private static $instance = null;
     
       public static function getInstance() {
     
            if (!self::$instance) {
                self::$instance = new PDO("mysql:host=".DB_HOST.";dbname=".DB_DATABASE, DB_USERNAME, DB_PASSWORD);
                self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            }
            return self::$instance;
        }
     
    }
    Il est difficile de trouver de la documentation sur le singleton.. Est ce que celui ci est parfaitement sécurisé ?

    Cordialement

  8. #8
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    C'est l'expression la plus simple du pattern Singleton, y'a pas grand chose à en dire. Coté sécurité, je ne vois rien de choquant là dedans si ce n'est que j'aurais mis les constantes sous forme de paramètres (optionnels évidement) de la méthode getInstance mais à toi de voir ce qui te va le mieux.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 75
    Points : 73
    Points
    73
    Par défaut
    Ok je te remercie pour ta réponse clair, simple et rapide

  10. #10
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    FYI si tu es en PHP 5.3, tu peux utiliser __callStatic pour utiliser les méthodes d'instances de PDO comme des méthodes de classe de DB:
    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
    class DB
    {
     
       private static $instance = null;
     
       public static function getInstance() {
     
            if (!self::$instance) {
                self::$instance = new PDO("mysql:host=".DB_HOST.";dbname=".DB_DATABASE, DB_USERNAME, DB_PASSWORD);
                self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            }
            return self::$instance;
        }
     
      public function __callStatic ($method, $args) {
        if (!is_callable(self::getInstance(), $method))
          throw new BadMethodCallException("No such method $method for DB");
     
        return call_user_func_array(array(self::getInstance(), $method), $args);
      }
    }
    De cette façon tu peux directement faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $stmt = DB::prepare($query); 
    // ou
    $stmt = DB::query($query);
    Je te rappelle qu'il faut à tout prix éviter le couplage de la classe DB avec d'autres classe qui utilisent la base de données, le meilleur moyen d'y parvenir est d'utiliser une référence à l'objet PDO (obtenu avec DB::getInstance) qui sera passée au constructeur des dites classes.

    Ex:
    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
    // ne pas faire
    class Utilisateur {
      public function getAll () {
         $query = "SELECT * FROM utilisateurs";
         $stmt = DB::query($query);
         return $stmt->fetchAll(PDO::FETCH_ASSOC);
      }
    }
     
    // faire
    class Utilisateur {
      protected $_pdo;
      public function __construct (PDO $pdo) {
        if (!$pdo) throw new InvalidArgumentException("First argument is expected to be a valid PDO instance, NULL given");
        $this->_pdo = $pdo;
      }
      public function getAll () {
        $query = "SELECT * FROM utilisateurs";
        $stmt = $this->_pdo->query($query);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
      }
    }
    Pourquoi ? Tout simplement pour une raison de couplage fort. Si la classe DB change, alors toutes les classes qui l'utilisent devront changer avec elle. Alors que dans le second exemple, tu peux changer la classe DB comme tu veux sans impacter les autres classes.

Discussions similaires

  1. Singleton dans classe de base et héritage
    Par Wil14 dans le forum C#
    Réponses: 12
    Dernier message: 22/12/2010, 16h18
  2. [PDO] [PDO] classe de connexion et d'execution
    Par Madfrix dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 07/05/2010, 11h26
  3. Pattern singleton ou Classe avec méthodes statiques ?
    Par Claythest dans le forum Langage
    Réponses: 3
    Dernier message: 11/12/2006, 11h28
  4. [introspection][singleton] introspetion de classe à singleton
    Par Jaxofun dans le forum API standards et tierces
    Réponses: 7
    Dernier message: 18/08/2005, 09h59
  5. fonctionnement de la classe Singleton
    Par lepoutho dans le forum C++
    Réponses: 11
    Dernier message: 04/08/2005, 09h28

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