Accueil > Forum > > > > PDO + singleton
PDO + singleton
dimanche 11 octobre 2009 à 22:49:39 |
PDO + singleton

eltyty
|
Bonjour,
J'ai réalisé un code pour réaliser une connexion "singleton" avec PDO or j'ai une erreur.
Voilà le code du singleton :
Code PHP :
class connexion_serveur {
/**
* instance de la classe pdo
*/
private $pdoinstance = null;
/**
* instance de la classe spdo
*/
private static $instance = null;
private function __construct() {
try {
$this->pdoinstance = new pdo(db_dsn, db_user, db_password);
$this->pdoinstance->query("set names utf8");//for using utf-8
$this->pdoinstance->query("set character set 'utf8'");//for using utf-8
}
catch (pdoexception $e){
echo 'erreur : '.$e->getmessage().'<br>';
die();
}
}
/**
* crée et retourne l'objet spdo
*/
public static function getinstance()
{
if(is_null(self::$instance)or !isset(self::$instance)) {
self::$instance = new connexion_serveur();
}
return self::$instance;
}
/**
* empeche la copie externe de l'instance
*/
private function __clone() {
throw new exception('le clonage de spdo n\'est pas autorisé');
}
}
Et maintenant j'essaie de faire une requête en PDO :
Code PHP :
$db=connexion_serveur::getinstance();
$insert = "insert into logs_erreurs (date_erreur, texte_erreur) values (?, ?)";
$statement = $db->prepare($insert);
$statement->bindparam(1, "test", pdo::param_str);
$statement->bindparam(2, "texte", pdo::param_str);
$statement->execute();
Et du coup j'obtiens : Call to undefined method Connexion_serveur::prepare()
Je début au niveau de PDO.
Merci de votre aide car après je compte mettre une class pour les requêtes qui utilisera cette connexion singleton.
|
|
dimanche 11 octobre 2009 à 23:13:20 |
Re : PDO + singleton

neigedhiver
|
Salut,
Tu ne t'y prends pas correctement, pour instancier ton singleton.
Le constructeur est la fonction qui est TOUJOURS exécutée lorsque la classe est instanciée, c'est à dire immédiatement après sa création, de manière automatique.
Le singleton, en terme de motif de conception, est une version bien particulière de la factory. La factory (ou usine) est censée instancier un objet adapté à certains paramètres. Là, l'usine construit l'instance et la retourne si elle existe déjà.
L'instanciation doit donc se faire dans la méthode getInstance() :
Code PHP : public static function getinstance() {
null === self::$instance or self::$instance = new self();
return self::$instance;
}
Plus parlant, le code suivant est synonyme :
Code PHP : public static function getinstance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
Les méthodes de PDO doivent être appelées sur l'objet instancié, pas en tant que méthodes statiques (ce qu'elles ne sont pas, et qui ne fonctionnera donc pas).
Plusieurs possibilités dans ton code. Soit tu stockes l'instance dans une variable, soit tu l'utilises directement. Depuis PHP5, les objets sont TOUJOURS passés par référence, ce ne sera donc pas une copie, mais l'objet lui-même qui sera alors stocké (donc s'il est modifié, il sera modifié partout ailleurs où il est utilisé). De plus, il n'était pas possible en PHP4 de chainer les appels de méthodes : si une méthode retournait un objet, il n'était pas possible d'appeler directement une méthode de cet objet, il fallait le stocker dans une variable intermédiaire puis appeler la méthode sur cette variable... Du coup, en PHP5, on peut faire ça :
Code PHP : connexion_serveur::getinstance() -> query('select nom from table') -> fetchobj() -> nom;
Ou alors :
Code PHP : $db = connexion_serveur::getinstance();
$db -> prepare('select login, password from users where login=:login limit 1');
$db -> bindvalue(':login', $_post['login'], pdo::param_str);
$db -> execute();
Hum... Je viens de voir que tu instancies déjà ta classe dans getInstance() ^^
Côté perfs, is_null() est moins rapide que de tester une égalité stricte avec NULL
Sinon, dans ton constructeur, tu NE DOIS PAS instancier un nouvel objet PDO. Il est préférable d'étendre la classe PDO :
Code PHP : class connexion_serveur extends pdo {
public function __construct() {
parent::__construct($dsn, $username, $password);
}
}
Euh bon, du coup, ma réponse est un peu désorganisée... :)
--
Neige
N'hésitez pas à lire la doc
|
|
dimanche 11 octobre 2009 à 23:22:52 |
Re : PDO + singleton

neigedhiver
|
En fait, si, tu peux instancier un nouvel objet PDO dans ton constructeur et le stocker dans une propriété. Mais c'est inutile. Mais tu peux.
Si tu veux VRAIMENT faire ça, pour accéder aux propriétés et aux méthodes de l'objet PDO, il faut que ta classe fonctionne comme un proxy, grâce aux méthodes statiques __call(), __get() et __isset(), qui vont respectivement appeler une méthode de l'objet PDO, retourner une propriété, et vérifier si une propriété existe.
C'est pour cela que quand tu appelles une méthode de PDO sur ton objet Connexion_serveur ça ne fonctionne pas...
Mais vraiment, il est plus simple d'étendre la classe PDO, un proxy dans ce cas n'est absolument pas adapté ni en terme de conception ni en terme de performances.
Voilà :)
--
Neige
N'hésitez pas à lire la doc
|
|
lundi 12 octobre 2009 à 08:45:04 |
Re : PDO + singleton

syndrael
|
Oups.. pas le temps de lire toute la réponse mais elle a le mérite de me rappelle la notion du OR qui peut être sympa. Merci de l'avoir fait remonter de mes souvenirs de 'mysql_query or die'
S.
|
|
lundi 12 octobre 2009 à 13:45:22 |
Re : PDO + singleton

eltyty
|
Bonjour,
Et bien là je suis au taff mais je relis ça se soir et je te dis ça. En tout cas déjà merci pour ces explications.
|
|
lundi 12 octobre 2009 à 14:55:24 |
Re : PDO + singleton

eltyty
|
Alors je prends un peux de temps là, au taff mais bon. Mais en relisant le tout c'est un peu confus.
En gros :
-la modification sur public static function getInstance() ok sans pb
-erreur quant au constructeur pas sûr d'avoir compris l'erreur et ce qu'il faut faire en fait.
Donc je dois faire une classe étendue du style :
Code PHP :
class connexion_serveur extends pdo {
public function __construct() {
parent::__construct($dsn, $username, $password);
try {
$this->pdoinstance = new pdo(db_dsn, db_user, db_password);
$this->pdoinstance->query("set names utf8");//for using utf-8
$this->pdoinstance->query("set character set 'utf8'");//for using utf-8
}
catch (pdoexception $e){
echo 'erreur : '.$e->getmessage().'<br>';
die();
}
}
}
Mais dans ce cas je laisse le constructeur de ma classe initiale vide ?
Du coup dans classe initiale j'obtiens :
Code PHP :
class pdo {
/**
* instance de la classe pdo
*/
private $pdoinstance = null;
/**
* instance de la classe spdo
*/
private static $instance = null;
private function __construct() {
}
/**
* crée et retourne l'objet spdo
*/
public static function getinstance()
{
if(null === self::$instance or !isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* empeche la copie externe de l'instance
*/
private function __clone() {
throw new exception('le clonage de spdo n\'est pas autorisé');
}
}
Et après je peux utiliser classiquement mon prepare pour les insert, select, etc. comme suit :
Code PHP :
$db = connexion_serveur::getinstance();
$db -> prepare('select login, password from users where login=:login limit 1');
$db -> bindvalue(':login', $_post['login'], pdo::param_str);
$db -> execute();
je sais que ces questions doivent paraître bête mais...
Merci
|
|
lundi 12 octobre 2009 à 15:08:03 |
Re : PDO + singleton

neigedhiver
|
Non, dans ton constructeur tu NE DOIS PAS instancier d'objet PDO, puisque l'objet qui est en cours de construction est justement un objet PDO !
Il faut cependant appeler le constructeur de la classe parente (PDO) :
parent::__construct($dsn, $username, $password);
Du coup, dans ton constructeur, au lieu de faire $this -> pdoinstance -> method(); tu fais : $this -> method()
Ton objet hérite bien entendu des méthodes de la classe PDO (c'est ce à quoi sert d'étendre une classe)
--
Neige
N'hésitez pas à lire la doc
|
|
lundi 12 octobre 2009 à 16:32:34 |
Re : PDO + singleton

eltyty
|
K,
je look vite fais mon boss est pas là. Je test ce soir en espérant que j'ai tout compris. Je m'attendais à ce que tu modifis le code s'il n'était pas bon mais je regarde ça ce soir.
Merci déjà 
|
|
mardi 13 octobre 2009 à 13:46:43 |
Re : PDO + singleton

eltyty
|
Re,
alors j'ai tenté ceci mais il me manque qq chose :
Code PHP :
class pdo {
public function __construct() {
try {
$this->PDOInstance = new PDO(DB_SESSIONS_DSN, DB_SESSIONS_USER, DB_SESSIONS_PASSWORD);
$this->PDOInstance->query("SET NAMES utf8");//FOR USING UTF-8
$this->PDOInstance->query("SET CHARACTER SET 'utf8'");//FOR USING UTF-8
}
catch (PDOException $e){
echo 'Erreur : '.$e->getMessage().'<br>';
die();
}
}
}
class Connexion_serveur extends pdo{
/** Instance de la classe SPDO */
private static $instance = null;
private function __construct() {
parent::__construct();
}
/** Crée et retourne l'objet SPDO */
public static function getInstance()
{
if(null === self::$instance OR !ISSET(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**Empeche la copie externe de l'instance */
private function __clone() {
throw new Exception('Le clonage de SPDO n\'est pas autorisé');
}
}
et j'appelle de cette manière :
Code PHP :
$db=Connexion_serveur::getInstance();
$insert = "INSERT INTO logs_erreurs (date_erreur, texte_erreur) VALUES (?, ?)";
$statement = $db->prepare($insert);
$statement->bindParam(1, "test", PDO::PARAM_STR);
$statement->bindParam(2, "texte", PDO::PARAM_STR);
$statement->execute();
Mais j'obtiens une erreur alors que je pensais avoir compris...
Help 
|
|
mardi 13 octobre 2009 à 13:56:49 |
Re : PDO + singleton

neigedhiver
|
Pourquoi est-ce que tu redéfinis la classe PDO ? PHP ne devrait pas aimer, parce qu'on ne peut pas définir une classe qui l'est déjà.
D'où l'extension de la classe PDO, ça, tu peux le faire.
Donc ce code :
Code PHP : try {$this->PDOInstance = new PDO(DB_SESSIONS_DSN, DB_SESSIONS_USER, DB_SESSIONS_PASSWORD);
$this->PDOInstance->query("SET NAMES utf8");//FOR USING UTF-8
$this->PDOInstance->query("SET CHARACTER SET 'utf8'");//FOR USING UTF-8
}
catch (PDOException $e){
echo 'Erreur : '.$e->getMessage().'<br>';
die();
}
tu dois le mettre dans le constructeur de ta classe. Et encore, sans le bloc try...catch, qui n'a rien à faire dans la classe : la classe génère une erreur si l'instanciation ne se déroule pas correctement (mauvais paramèrtes, connexion impossible, etc). La gestion des erreurs doit donc se faire à l'extérieur, ce n'est PAS le rôle de la classe de faire ça. A toi de déclarer, éventuellement, un gestionnaire d'exceptions personnalisées, ou de de mettre des blocs try...catch là où c'est nécessaire.
En gros, le constructeur de ta classe doit ressembler à ça :
Code PHP : public function __construct($dsn, $username, $password) {
parent::__construct($dsn, $username, $password);
$this -> query("SET NAMES utf8");
$this -> query("SET CHARACTER SET 'utf8'");
}
Et surtout, supprime la déclaration de ta classe PDO, elle existe déjà ;)
Etendre la classe PDO permet justement d'apporter à PDO des fonctionnalités qu'elle n'a pas et dont tu as besoin. Parmi ces fonctionnalités, on peut trouver l'automatisation de certaines tâches à l'instanciation, comme justement, la connexion en UTF8.
--
Neige
N'hésitez pas à lire la doc
|
|
Cette discussion est classée dans : code, connexion, instance, singleton, pdo
Répondre à ce message
Sujets en rapport avec ce message
Singleton encore [ par eltyty ]
Bonjour, je ne comprends pas pourquoi j'ai une erreur. J'essaie d'utiliser le singleton mais je n'arrive pas à appeler une fonction à l'intérieur. Vo
connexion Myslq PDO [ par vargas ]
Bonjour à tous me voila avec une autre question présentement j'ai un fichier fonctions.php qui est une classe qui extend de PDO dans laquelle j'ai t
connexion PDO [ par vargas ]
Bonjour je voudrais créer une classe connexion à ma bd MySql et une autre classe qui vas contenir toutes mes requêtes. Pour le le moment j'ai ça :
connexion sqlite en php5 [ par Karibot ]
Bonjour, j'ai un problème lorsque je me connecte à une base sqlite avec sqlite_open. en fait, j'ai une erreur me disant que ma table n'existe pas mais
procedure stockée avec parametre en sortie avec PDO/MySQL [ par poland_power ]
Hello m'sieurs dames, en esperant que l'un de vous puisse m'aider, je vous expose mon soucis. j'ai une procédure stockée nommée avec un parametre de
Formulaire d'ajout dans la base [ par sarrayosra ]
salut, J'ai fais un formulaire d'ajout des employés dans la base de donnée et j'ai beaucoup de faute dans le code php, s'il vous plais quelqu'un m'ai
Singleton : intérêt et bon fonctionnement ? [ par eltyty ]
Bonjour, je suis en train de me mettre sur la notion de singleton afin d'obtenir une seul connexion mais du coup j'ai quelques questions. Actuellemen
PDO serveur BDD distant [ par TheGorgo ]
Bonjour, Je cherche à me connecter à un serveur de base de données distante en utilisant Doctrine. Lorsque je veux générer mon schèma de données, j'a
connexion mysql impossible [ par nounours21_6 ]
Bonjour tout le monde, Je dois développer un site en PHP et evidement je dois me connecter à une BDD! Ce n'est pas mon premier dev en PHP mais la j
connexion à deux bases de données au meme temps via PDO [ par bouchenebfateh ]
Bonjour à tous , je suis débutant en php OOP, je suis entrain de développer une application qui possède 2 bases de données, du coup je suis bloqué su
Livres en rapport
|
Derniers Blogs
POUR RAPPEL ! LES SPéCIFICATIONS DES PROTOCOLES OFFICE ET SHAREPOINT SONT DISPONIBLES SUR MSDNPOUR RAPPEL ! LES SPéCIFICATIONS DES PROTOCOLES OFFICE ET SHAREPOINT SONT DISPONIBLES SUR MSDN par neodante
Quelle est le point commun entre : Microsoft il y a 10 ans et Apple aujourd'hui ? Réponse: avoir une politique de protocoles propriétaires et fermés :) Car pour rappel (si si je vous assure c'est important de le rappeler), la majorité des spécifications e...
Cliquez pour lire la suite de l'article par neodante JOYEUX ANNIVERSAIRE NIXJOYEUX ANNIVERSAIRE NIX par ebartsoft
Souhaitons un bon et joyeux anniversaire à notre hôte à tous, Nix.
Je ne le répéterais jamais assez mais sans lui rien ne serait possible. Il défit en permanence les lois de la gravité et comme il le dit si bien, si tu lui fais confiance ça devra...
Cliquez pour lire la suite de l'article par ebartsoft IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc
Forum
BALISE D'ANCREBALISE D'ANCRE par FADEST
Cliquez pour lire la suite par FADEST
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|