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]


Sujet :

PHP & Base de données

  1. #1
    Membre régulier
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2007
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2007
    Messages : 112
    Points : 74
    Points
    74
    Par défaut singleton
    Bonjour à tous

    pour faire simple, j'essaie de faire un singleton sur un object PDO.

    Voici la classe de cette objet
    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
     
    class instanceDB {
     
     	private static $instance = NULL;
    	private $db;
     
    	/**
    	 * Constructor
    	 */
    	function __construct(){
    		try {
    			$this->db = new PDO('mysql:host=host;dbname=db', 'login', 'pwd');
    		}
    		catch(PDOException $e) {
    			print "Erreur PDO ! : " . $e->getMessage() . "<br/>";
    			die();
    		}
    	}
     
    	public static function getInstance() {
    		if( !(self::$instance) ) {
    			self::$instance = new instanceDB();
    		}
    		return self::$instance;
    	}
     
    	function getDB(){
    		return $this->db;
    	}
    }
    Par contre après, quand je lance ce code
    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
     
    require_once 'instanceDB.php';
    class table {
     
    	private $insert;
     
    	public function __construct() {
    		$instanceDB = instanceDB::getInstance();
    		var_dump($instanceDB->getDB());
    		$this->insert = $instanceDB->getDB()->prepare('INSERT INTO table (id) VALUES 0');
    	}
     
    	public function insert() {
    		$this->insert->execute();
    		return $this->insert->rowCount();
    	}
     
    }
    J'obtiens
    object(PDO)#2 (0) { }
    Fatal error: Call to a member function prepare() on a non-object in ..table.php
    Lorsque j'instancie une fois mon object PDO mais sans classe singleton, le var_dump() retourne la même chose et tout fonctionne!

    Des idées?
    Merci d'avance!

  2. #2
    Membre émérite Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Points : 2 566
    Points
    2 566
    Par défaut
    Bonjour, teste ceci :

    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    class instanceDB {
     
     	private static $instance = NULL;
     
    	public static function getInstance() {
    		if(self::$instance === null) {
    			try {
    				self::$instance = new PDO('mysql:host=host;dbname=db', 'login', 'pwd');
    			}
    			catch(PDOException $e) {
    				print "Erreur PDO ! : " . $e->getMessage() . "<br/>";
    				die();
    			}
    		}
    		return self::$instance;
    	}
    }
     
     
     class table {
     
    	private $insert;
     
    	public function __construct() {
    		$this->insert = instanceDB::getInstance()->prepare('INSERT INTO table (id) VALUES 0');
    	}
     
    	public function insert() {
    		$this->insert->execute();
    		return $this->insert->rowCount();
    	}
     
    }

  3. #3
    Membre régulier
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2007
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2007
    Messages : 112
    Points : 74
    Points
    74
    Par défaut
    Ahhh YES

    Par contre t'aurais pas une ou deux précisions parce qu'en dehors du fait que le code est simplifié, je vois pas pourquoi mon code ne fonctionne pas !

    En tout cas merci

  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
    Points : 3 947
    Points
    3 947
    Par défaut
    Salut

    Le problème c'est que tu dis "ça ne fonctionne", et du coup ça ne veut pas dire grand chose.
    Faut expliquer qu'est ce qui ne fonctionne pas, ou/et si tu as un message d'erreur, et bien le poster.

    D'ailleurs, n'as tu pas un message d'erreur ?

    Il y a un truc qui théoriquement n'est pas logique : private static $instance = NULL;
    Déclarer static sur une propriété c'est pour pouvoir l'exploiter en dehors de la classe (sans même l'instancier d'ailleurs).
    Cependant, la visibilité private c'est pour protéger une propriété (ou méthode) afin quelle soit exploitée que dans la classe, et non pas à l'extérieur, même dans une classe fille.

    Du coup, faire private static $une_proprite n'est pas correcte, et théoriquement tu devrais avoir une erreur lorsque tu appel instanceDB::getInstance()


    Théoriquement, $instance doit être static dans ton cas alors il vaut mieux le déclarer en public :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public static $instance = NULL;
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Points : 64
    Points
    64
    Par défaut
    Bonjour à tous.

    RunCodePHP, c'est la staticité de $instance qui garantit son unicité, ce qui est le cœur même du singleton.

    D'autre part, un attribut (ou méthode) static non public n'a rien d'illogique.

    Tu pars du principe que static est fait pour utiliser un attribut ou une méthode "en dehors de la classe". C'est erroné. Quelque chose de statique dans une classe, c'est quelque chose qui ne varie pas d'une INSTANCE à l'autre de la classe.
    C'est donc quelque chose de COMMUN à la classe et à toutes ses instances. Si ce "quelque chose" est lié à des comportements encapsulés, il devra être privé.

    En l'occurrence, c'est exactement le cas ici, si $instance était public, comment garantir que getInstance() renvoie toujours la même instance d'objet ?

    D'ailleurs, toutes les mises en oeuvre du singleton présentées ici sont incorrectes.

    Aucune n'empêche d'avoir 2 instances du même objet. Vous utilisez ici le singleton pour rendre votre connexion BDD globale, c'est une grosse confusion.

    Si vous vouliez vraiment créer un singleton avec le PDO, voici la marche à suivre. Notez que le constructeur est privé aussi :

    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
    class instanceDB extends PDO {
     
     	private static $instance = NULL;
     
    	/**
    	 * Constructor
    	 */
    	private function __construct($dsn, $username, $password, $driver_options = array()){
    		parent::__construct($dsn, $username, $password, $driver_options);
    	}
     
    	public static function getInstance() {
    		if (self::$instance === null) {
                        try {
    	                self::$instance = new self('mysql:host=host;dbname=db', 'login', 'pwd'));
    		    }
    		    catch(PDOException $e) {
    			print "Erreur PDO ! : " . $e->getMessage() . "<br/>";
    			die();
    		    }
    		}
     
    		return self::$instance;
    	}
    }
    Et encore, ça pose peut-être des soucis au niveau de la gestion des paramètres optionnels. Le problème de base est que le singleton n'a rien à voir avec tout ça.

    TekFanatiX, si tu veux accéder à ta connexion BDD "partout", tu la récupères simplement via une méthode statique dans une classe de fournitures ressources, c'est un "bootstrap" que tu essaies de faire, pas un singleton.

  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
    Points : 3 947
    Points
    3 947
    Par défaut
    RunCodePHP, c'est la staticité de $instance qui garantit son unicité, ce qui est le cœur même du singleton.

    D'autre part, un attribut (ou méthode) static non public n'a rien d'illogique.
    Effectivement, tu as parfaitement raison.

    Je t'avoue que j'en était quasi convaincu.
    C'est quelque part rassurant de se voir raconter autant de conner* ... ça m'fera les pieds tiens

    Ceci dit, si j'avais pris soin 2 secondes pour regarder mon code (car j'utilise aussi PDO et en singleton), j'aurais remarqué que je l'avais mis en protected (et non pas public).
    Et bien du coup (j'ai bien fait de l'ouvrir finallement), j'en est profité de corriger ça, et bien sûr ça fonctionne parfaitement bien, aucune erreur comme je l'avais cru.
    Donc merci à toi d'avoir pris de le temps de corriger mes gros aprioris.


    Par contre, pour ce qui est de mettre le constructeur en privé, là, c'est le coup d'bâton :
    Fatal error: Access level to PdoMySQL::__construct() must be public (as in class PDO)
    A priori, on ne peu pas faire autrement que le conserver en public.


    D'ailleurs, toutes les mises en oeuvre du singleton présentées ici sont incorrectes.

    Aucune n'empêche d'avoir 2 instances du même objet. Vous utilisez ici le singleton pour rendre votre connexion BDD globale, c'est une grosse confusion.
    Il y avait un membre qui avait posté dans un topic une astuce pour verrouiller ça, pour empêcher la duplication de l'instance PDO, mais je ne parviens pas à remettre la main dessus.

    Par contre, comme j'ai adopté son astuce, alors je t'en fais part, et si tu as quelques minutes tu pourrais dire ce que tu en pense.

    (Je simplifie un peu, j'y mets juste l'essentiel, le principe)
    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
     
    class PdoMySQL extends PDO {
        private static $instancePdo = null;
        private static $verrou = true;
     
        public function __construct() {
            if (self::$verrou) {
                throw new PDOException('[Singleton] Présence d\'une instance de la classe '.__CLASS__);
            }
            else {
                self::$instancePdo = parent::__construct('mysql:host='.SERVER.';dbname='.DATABASE, USERNAME, PASSWORD);
            }
        }
     
        public static function getInstance() {
            if (self::$instancePdo == null) {
                self::$verrou = false;
                self::$instancePdo = new PdoMySQL();
                self::$verrou = true;
            }
            return self::$instancePdo;
        }
     
        ... etc ...
    }
    Ceci me parais simple est efficace.
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Points : 64
    Points
    64
    Par défaut
    A mon tour de me flageller, j'étais également convaincu que changer l'accessibilité du constructeur en héritant échouerait, mais je postais d'une machine vieillissante où je n'avais rien de confortable pour tester rapidement le code .

    Encore une fois, le singleton est un pattern très particulier qui répond à des problématiques particulière, la plupart du temps intimement liées aux fonctionnalités de la classe. Donc hériter d'une classe non singleton pour en faire un singleton, ça reste un exemple torturé.

    L'astuce du verrou est sympathique

    Mais pour revenir sur mes propos précédents, le problème et la solution de TekFanatiX n'ont rien à voir avec le singleton. En effet, garantir l'unicité de l'instance du PDO n'a pas d'enjeu critique en terme de conception.

    Je me permet de penser que l'idée est de n'utiliser qu'une connexion ouverte pour une séquence d'actions diverses à effectuer sr une BDD lors d'une résolution d'action.

    Je me permet également d'exposer rapidement comment je m'organise pour cela, parce que je trouve le problème intéressant et que RunCodePhp est toujours interessé par le sujet.

    Je repars de la classe Table de TekfanatiX. Celle ci est couplée à son "instanceDB". Dommage dans un contexte qui utilise une extension très générale comme PDO.

    Ce qui me parait sain, c'est de passer un paramètre de type PDO au méthodes de la classe Table ou toute autre classe qui servirait d'indirection vers une BDD, ou de DAO, ou d'ORM.
    C'est alors à la couche qui utilise la classe de gérer la connexion, quelque en soient les enjeux : unicité ou non, ouverture préalable, gestion de transactions en amont et en aval des appels à la classe Table, ou autre...

    Dans un conception MVC, la classe Table fera partie des Modèles, et ça sera les contrôleurs par exemple qui se chargeront d'ouvrir la connexion. Peut-être à l'aide d'une classe ressemblant à l'instanceDB présentée, mais les modèles n'y seront pas couplés, et donc réutilisables dans d'autres points d'entrée vers la BDD, sans contraindre les choix de gestion de la connexion.

    Dans une application MVC réalisée avec le Zend Framework par exemple, on récupèrerait la connexion auprès d'une classe de bootstrap.

  8. #8
    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
    Points : 3 947
    Points
    3 947
    Par défaut
    Citation Envoyé par pandrogynik
    Ce qui me parait sain, c'est de passer un paramètre de type PDO au méthodes de la classe Table ou toute autre classe qui servirait d'indirection vers une BDD, ou de DAO, ou d'ORM.
    C'est alors à la couche qui utilise la classe de gérer la connexion, quelque en soient les enjeux : unicité ou non, ouverture préalable, gestion de transactions en amont et en aval des appels à la classe Table, ou autre...
    Je suis entièrement d'accord avec toi, et je l'ai aussi lu à plusieurs reprise.

    Cependant, sans vouloir chercher une bonne ou une mauvaise excuse, je pense qu'il faut aussi prendre en compte le contexte dans sa généralité.

    En 1er, et bien je prends mon cas (et il doit en avoir beaucoup d'autres dans le même cas), ce sont mes connaissances qui me permettent pas d'approfondir la question.
    Le concept du singleton je l'ai découvert il y a même pas un an, même chose pour le problème de dépendance entre classes/objet.

    Puis l'autre, c'est le projet en lui même qui est modeste, même très modeste.
    Faut il pousser le développement d'un projet en respectant obligatoirement un concept, comme le MVC ?
    Ma réponse, du moins mon avis est non, car même si je ne maitrise pas ce concept de MVC (y compris DAO, ORM), j'en ai téléchargé quelques uns juste pour voir, mon sentiment c'est que cela va inévitablement avoir une incidence négative sur les performances.

    Faire compliqué juste pour faire compliqué parce qu'il est dit qu'il faut respecter un concept, ça, je ne suis pas convaincu.

    Donc pour le moment, le concept de singleton tel qu'il codé plus haut me va comme un gant, car il est simple à comprendre, et rapide à réaliser, ce n'est pas une usine à gaz, donc tout autant facile à débugger en cas de problème.
    Aussi, je me vois pas utiliser une autre BDD que MySQL dans le futur, donc me fermer les portes à ce niveau là ne me dérange pas, même si conceptuellement ce n'est pas zen.


    En faite, j'ai basculé en grande partie vers PDO pour 3 raisons majeurs, la 1ère c'est que la communauté Php a annoncé que cette classe est vouée à remplacer les mysql_*, ensuite le principe des requêtes préparées me plaisait beaucoup, aussi bien le coté sécurité que le coté pratique, et en 3ème c'est que c'est une classe donc on est de suite dans un contexte objet.


    Ceci dit, et comme dirait l'autre, "il y a que les imbéciles qui ne changent pas", donc peut être qu'avec le temps je prônerais tout l'inverse.
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Points : 64
    Points
    64
    Par défaut
    Entièrement d'accord, la meilleure conception est la mieux dimensionnée par rapport au projet, et j'ai déjà utilisé plusieurs fois des techniques similaires à ce "singleton".

    Je crois que ma conclusion finale serait qu'on va simplement chercher trop loin en parlant de singleton.

    Un "lieu" où stocker un PDO statique est en fait le nécessaire et suffisant pour s'y prendre de cette façon.

    Sur un petit projet, on en arriverait à une sorte de "registre" statique avec les ressources réutilisables dans toute l'appli :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Resources
    {
        public static $ma_connex_bdd;
        public static $mon_socket_reseau;
        public static $mon_client_soap;
        // ...
    }
    On les instancie/ouvre au début de son index, et on les utilise d'où on veut quand on veut.

    Pour un projet un peu plus que petit, qui tend vers le moyen, on les passera effectivement protected, et ajoute des "get" qui font le test === null pour éviter de trop faire de doublons par inattention...

    Mais bon, on s'écarte, pour ce qui est de problème de départ, manifestement le test self::$instance === null se sera avéré plus efficace que le !self::$instance.

    Bonne continuation.

  10. #10
    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
    Points : 3 947
    Points
    3 947
    Par défaut
    Citation Envoyé par pandrogynik
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Resources
    {
        public static $ma_connex_bdd;
        public static $mon_socket_reseau;
        public static $mon_client_soap;
        // ...
    }
    On les instancie/ouvre au début de son index, et on les utilise d'où on veut quand on veut.
    Ca me semble vachement intéressant ça.

    La grosse difficulté que je rencontre actuellement, c'est l'ordre des instanciations des différentes classes car certaines classes demandent (ou réclament) qu'une autre soit faite avant car elle l'exploite.
    Peut être (sinon surement) que c'est ma manière de faire qui cause problème.


    Le faire d'avoir des objets de manière static ne provoque t-il pas d'autres problèmes en cascade ?
    En tout cas, en se qui concerne les Objets qui doivent être des singletons, j'y voit là une excellente idée, ou concept.
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  11. #11
    Membre expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Points : 3 972
    Points
    3 972
    Par défaut
    Bonjour,

    Dans le code ci-dessus, le verrou pourrait-être remplacé par un test de nullité de instancePdo, ou mieux : un constructeur privé
    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 PdoMySQL extends PDO {
        private static $instancePdo = null;
     
        private function __construct() {   
                self::$instancePdo = parent::__construct('mysql:host='.SERVER.';dbname='.DATABASE, USERNAME, PASSWORD);
        }
     
        public static function getInstance() {
            if (self::$instancePdo === NULL) {
                self::$instancePdo = new PdoMySQL();
            }
            return self::$instancePdo;
        }
    }

  12. #12
    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
    Points : 3 947
    Points
    3 947
    Par défaut
    Citation Envoyé par RunCodePhp
    Par contre, pour ce qui est de mettre le constructeur en privé, là, c'est le coup d'bâton :
    Fatal error: Access level to PdoMySQL::__construct() must be public (as in class PDO)
    A priori, on ne peu pas faire autrement que le conserver en public.
    Il me semble qu'on est dans cas particulier ici avec PDO, car comme indiqué ci-dessus, on ne peu pas déclarer en private le constructeur, donc pas autre choix que de le mettre en public.

    Du coup, on aura tout le loisir d'instancier autant de fois PDO.
    L'astuce du verrou était là pour ça.

    Ca y est, j'ai remis la main sur le topic, c'était Petibidon.
    -> http://www.developpez.net/forums/d88...e/#post5053656
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Points : 64
    Points
    64
    Par défaut
    Citation Envoyé par RunCodePhp Voir le message
    La grosse difficulté que je rencontre actuellement, c'est l'ordre des instanciations des différentes classes car certaines classes demandent (ou réclament) qu'une autre soit faite avant car elle l'exploite.
    L'encapsulation est là pour ça. Car ce sont bien des comportements qu'on encapsule, et pas des données.
    Tu passes tes ressources en protected, et tu les instancies via des méthodes qui garantiront les contraintes/dépendances qui peuvent exister entre les différentes ressources.
    Le faire d'avoir des objets de manière static ne provoque t-il pas d'autres problèmes en cascade ?
    Il n'y a pas de raison...surtout si on recours à l'encapsulation.

  14. #14
    Membre expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Points : 3 972
    Points
    3 972
    Par défaut
    Il me semble qu'on est dans cas particulier ici avec PDO, car comme indiqué ci-dessus, on ne peu pas déclarer en private le constructeur, donc pas autre choix que de le mettre en public.
    Haaa... tout s'explique

    Pour obtenir un constructeur privé pour PDO on peut faire çà, même si ca me parait trivial pour pas grand 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
     
    class PdoMySQL {
        private static $instance = null;
        private $pdo;
     
        private function __construct() {   
                self::$pdo = new PDO('mysql:host='.SERVER.';dbname='.DATABASE, USERNAME, PASSWORD);
        }
     
        public static function getInstance() {
            if (self::$instance === NULL) {
                self::$instance = new PdoMySQL();
            }
            return self::$instance;
        }
     
        public function __get($name){
            return $this->pdo->{$name};
        }
     
        public function __call($name, $args){
            return call_user_func_array(array($this->pdo, $name), $args);
        }
    }

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Points : 64
    Points
    64
    Par défaut
    Je suis désolé, mais j'en remet une couche, ceci n'est pas un singleton.

    Un singleton, c'est une classe A qu'on ne peut instancier qu'un fois. Et je n'ai aucun moyen de faire coexister 2 instances de A dans le même runtime. Dans l'exemple que tu montres, ThomasR, on a une classe A qui fournit une instance d'une classe B, et si je veux un deuxième B, je fais new B sans utiliser A.

    C'est pour cela que je dis depuis le début qu'on utilise le terme singleton à tort pour le problème de tekfanatik, on a juste à faire à un registre de ressources dont l'enjeu est une organisation propre.

    [Edit : grillé par ta réponse en plus ]
    STOOOP, je dis n'importe quoi, j'ai lu un peu trop vite, le pattern singleton est correct. Je t'approuve quand tu dis que ça ne sert pas à grand chose, puisque la classe délègue ses services à une classe disponible en non-singleton.

  16. #16
    Membre expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Points : 3 972
    Points
    3 972
    Par défaut
    e suis désolé, mais j'en remet une couche, ceci n'est pas un singleton.

    Un singleton, c'est une classe A qu'on ne peut instancier qu'un fois. Et je n'ai aucun moyen de faire coexister 2 instances de A dans le même runtime. A.
    Absolument pas...
    Mon exemple montres bien un singleton de la classe PdoMySQL uniquement accessible depuis la méthode getInstance()... Il est impossible d'obtenir une seconde instance puisque le constructeur est privé.

    Evidemment tu peux instancier autant d'instances de PDO que tu veux vu que le constructeur de la classe est publique.

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

Discussions similaires

  1. [Servlet]Singleton & cache
    Par lucimast dans le forum Servlets/JSP
    Réponses: 4
    Dernier message: 15/12/2004, 16h36
  2. Singleton héritable ?
    Par rolkA dans le forum C++
    Réponses: 10
    Dernier message: 11/12/2004, 16h22
  3. [Débutant] pattern singleton
    Par SirDarken dans le forum Débuter avec Java
    Réponses: 22
    Dernier message: 11/12/2004, 01h55
  4. Mutiple row in singleton select ????? [Important, merci]
    Par SkyDev dans le forum Bases de données
    Réponses: 6
    Dernier message: 20/04/2004, 14h02
  5. [debutant]Singleton
    Par bafman dans le forum Langage SQL
    Réponses: 6
    Dernier message: 13/01/2004, 15h41

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