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 :

Surcharger l'extension du singleton [PDO]


Sujet :

PHP & Base de données

  1. #1
    Membre éclairé
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Points : 773
    Points
    773
    Par défaut Surcharger l'extension du singleton
    Bonjour,

    Je me base sur le (méga) tuto Création d'objets métiers avec PDO de Julp, qui requiert de solides connaissances POO que je n'ai pas. D'où les questions de noob :

    Mes classes :
    - classe singleton PDO2, extension de la classe native PDO de PHP,
    - classe PDO3 extension de PDO2, avec des méthodes qui lui sont propres,
    - j'utilise ces 2 classes PDO2 et PDO3 distinctement: PDO2 pour pouvoir utiliser les méthodes natives de PDO, et PDO3 pour ses méthodes propres.

    Le problème qui me turlupine plus que fortement:
    Je voudrais pouvoir utiliser les méthodes natives de la classe PDO directement avec un objet de la classe PDO3. Or quand j'appelle une méthode PDO sur un objet créé avec la classe PDO3, PHP me jette.

    Par exemple, ceci ne fonctionne pas (a priori parce que la classe PDO3 ne connait pas les PDO::Statements) :
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $connexion = PDO2::getInstance();
    $pdo = new PDO3($connexion);
     
    $sql='SELECT truc, bidule FROM machin';
    $pdo->prepare($sql);

    Par contre, ceci fonctionne :
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $pdo= PDO2::getInstance();
    $sql='SELECT truc, bidule FROM machin';
    $pdo->prepare($sql);


    D'où les trois questions :

    1) Est-ce possible de surcharger les méthodes de PDO3 pour pouvoir utiliser les PDO::Statement directement sur un objet créé par la classe PDO3 ?

    2) Pour cela, est-ce que la seule méthode possible est d'utiliser la méthode magique __call($method, $args) ou bien faut-il redéfinir toutes les méthodes PDO dans la classe PDO3 ?

    3) Méthode magique __call:
    J'ai lu que cette méthode magique __call($method, $args) n'était implémentée qu'à partir de PHP5.3 (pas de chance, j'ai PHP5.2.9) mais dans le tuto de Julp (chap II.B.2), il est indiqué que cette méthode est buggée en dessous de PHP5.2.6, ce qui laisse sous-entendre que je pourrais l'utiliser avec PHP5.2.9. Est-ce le cas ou bien faut-il employer une autre tactique ?


    Merci d'avance

  2. #2
    Membre éclairé
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Points : 773
    Points
    773
    Par défaut
    Je me permets un petit up.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    625
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 625
    Points : 822
    Points
    822
    Par défaut
    Si je ne m'abuse, la méthode __call existe depuis PHP 5.0. Celle qui n'existe que depuis PHP 5.3 est __callStatic.

    Sans code difficile de voir, mais à vue de pied, tu n'as pas vraiment d'autre choix que de passer par __call pour renvoyer les appels de méthodes sur JPDO.

  4. #4
    Membre éclairé
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Points : 773
    Points
    773
    Par défaut
    Merci, j'avais fait une petite tentative mais sans aucun effet. Ceci conjugué aux doutes quant à la version PHP acceptant cette methode magique.

    Voila le code en version résumée :

    La classe PDO2 extension de PDO (génération du singleton)
    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
    35
    36
    37
    38
    39
    40
    41
    class PDO2 extends PDO {
     
    	protected $_dbname = 'my_base' ; // protected car utilisée dans classe fille PDO3
     
    	private static $_instance;
    	private static $_dsn	= 'mysql:host=127.0.0.1;dbname=my_base' ;
    	private static $_dbuser	= 'user' ;
    	private static $_dbpwd	= 'password' ;
     
    	private static $_debug	= false ;
    	private static $_ipadmin= 'XX.XX.XX.XX' ;
     
     
    	/* Constructeur : héritage public obligatoire par héritage de PDO */
    	public function __construct( ) {
    	}
     
    	/* Singleton */
    	public static function getInstance() {
     
    		if (!isset(self::$_instance)) {
     
    			try {
    				self::$_instance = new PDO(self::$_dsn , self::$_dbuser , self::$_dbpwd);
    			}
    			catch (PDOException $e) {
    				if ( self::$_debug === true && ($_SERVER['REMOTE_ADDR'] == self::$_ipadmin) ) 	{
    					echo '<br>/PDO2 Erreur N° : '.$e->getCode();
    					echo '<br/>PDO2 Erreur : '.$e->getMessage().'<br />';
    					die();
    				}
    				else {
    					echo 'Erreur de la classe PDO2 - passer en mode DEBUG';
    					die();
    				}
    			}
    		}
    		return self::$_instance; 
    	}
     
    }

    Un extrait de la classe PDO3 avec ses méthodes propres
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    class PDO3 extends PDO2 {
     
    	/* Variables de la classe */
    	private $_debug		= false;
    	private $_delimiter	= ',   '; 			// ne pas modifier !
    	private $_type_of_key = array('PRI', 'UNI', 'MUL') ;
    	protected $_pdo		= NULL;				// ne doit pas être "private" car héritage de PDO2
     
     
    	/* Constructeur : héritage public obligatoire par héritage de PDO */
    	public function __construct($pdo)
    	{
    		$pdo_ext = $this->checkPdoExtension();
     
    		if (isset($pdo) && $pdo_ext) {
     
    			$this->_pdo = $pdo;
     
    		}
    		else {
    			throw new PDOException("No pdo connection");
    		}
    	}
     
     
     
    	/* Destructeur */
    	public function __destruct() // nota: ne surtout pas mettre de parametre
    	{
    		$this->close();
    	}
     
     
     
    	/** 28/02/2010
    	* ferme la connexion à la dB (portage dans la classe PDO de la fonction mysql_close)
    	*/
    	public function close()
    	{
    		$this->_pdo = NULL;
    	}
     
     
     
    	/* Methode magique */
    	public function __toString($object)
    	{
    		$string = (string) $object ;
    		return $string;
    	}
     
     
    	/* Last Id  */
    	public function getLastInsertId()
    	{
    		$last_id = $this->_pdo->lastInsertId(); 
    		return $last_id;
    	}
    	public function countId($table_name, $id_name, $id_value) {
    		// méthode alternative : voir http://php.developpez.com/faq/?page=pdo#pdo-count
     
    		// #####
    		// NOTA: à modifier pour ne selectionner que les enregistrements de la PK (utiliser fonction existante)
    		// #####
     
    		$sql_prep = "SELECT COUNT(*) FROM $table_name WHERE $id_name= :id_value" ;
    		$query	= $this->_pdo->prepare($sql_prep) ;
    		$query->execute(array( ':id_value' => $id_value ));
    		$count = $query->fetchColumn();
    		$query->closeCursor();
    		return $count;
    	}
    etc...
    Et la façon dont j'utilise ces classes :

    par exemple pour PDO2
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $pdo= PDO2::getInstance();
    $sql='SELECT truc, bidule FROM machin';
    $pdo->prepare($sql);

    par exemple pour PDO3
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $connect = PDO2::getInstance();
    $pdo = new PDO3($connect);
    $field = 'truc_muche';
    $nbre_data_db = $pdo->countId($table_name, $field , $data_array[$field]) ;

    Donc je voudrais comprendre s'il faut que je réimplante ttes les méthodes PDO dans la classe PDO3 pour les utiliser directement avec un objet issu de cette classe, ou si cela fonctionnerait avec la méthode magique __call en PHP5.2.9 (d'après la doc, a priori oui, mais le doute m'habite)
    et à la nième relecture de mon magnifique code , je me dis aussi qu'il faudrait probablement réimplanter la méthode checkPdoExtension(); de PDO3 dans PDO2.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    625
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 625
    Points : 822
    Points
    822
    Par défaut
    En fait le soucis qui va se poser, c'est qu'en étendant PDO, tu ne passeras jamais par __call (vu que les méthodes de l'objet existent)
    En fait tes deux classes, si je me plante pas, étendent PDO sans vraiment étendre PDO.
    La première ne fait que renvoyer une instance de PDO qui est utilisée dans la seconde. Le problème c'est qu'au final, aucune des deux n'est une instance "bien formée" de PDO.

    Je sais pas si je suis très clair là à vrai dire...

  6. #6
    Membre éclairé
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Points : 773
    Points
    773
    Par défaut
    Salut

    Ce n'est pas limpide pour moi.

    Comment procéder ? Faut-t-il ne créer qu'une seule extension PDO et placer le singleton dans le constructeur, puis ajouter une méthode magique __call pour accéder aux méthodes natives de PDO ..?

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    625
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 625
    Points : 822
    Points
    822
    Par défaut
    Si tu tiens vraiment à un singleton, tu reprends le code de la classe JPDO en mettant le constructeur en private. Tu peux lui rajouter toutes les méthodes que tu veux ensuite au besoin.

    La seule chose importante si tu étends PDO, c'est d'appeler le constructeur de la super classe dans le constructeur de la classe fille.

  8. #8
    Membre éclairé
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Points : 773
    Points
    773
    Par défaut
    Bon avec un grand merci à PetitBidon
    ,

    Voila le principe de la classe Singleton permettant d'utiliser les méthodes PDOStatement.
    C'est clairement pas aussi transcendant que le tuto impressionnant de julp, mais pour le noob que je suis, ça marche et ça me suffit pour débuter avec PDO :


    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    class SinglePDO extends PDO{
    // Merci à PetitBidon
    // Cf http://www.developpez.net/forums/d888098/php/php-sgbd/pdo/surcharger-lextension-singleton/#post5046735
     
    /* ACCES au vrai-faux singleton depuis le code
     try {
    	$pdo = SinglePDO::getInstance();
     
    }
    catch (PDOException $e) {
    	echo 'ERR: ' .$e->getMessage().'<br/>';
    }
    */
     
     // Private static : Accessibles par self::ma_var_private
    	private static $instance;
    	private static $verrou = true;
    	private static $_dsn	= 'mysql:host=XXX.XXX.XXX.XXX;dbname=ma_base';
    	private static $_dbuser	= 'user' ;
    	private static $_dbpwd	= 'pwd' ;
     
    	// Private accessibles par $this->ma_var
    	private $_dbname = "ma_base" ;
    	private $_debug	= true ;
     
    	/* Constructeur */
    	public function __construct( $dsn , $uname, $upass ){
    		if( self::$verrou ) trigger_error( 'Construction interdite, mode singleton. Utilisez la méthode SinglePDO::getInstance' , E_USER_ERROR );
    		parent::__construct( $dsn , $uname, $upass  );	
    	}
     
    	/* Instance */
    	public static function getInstance( ){
    		if( self::$instance == null ){
    			self::$verrou = false;
    			self::$instance = new SinglePDO(self::$_dsn , self::$_dbuser , self::$_dbpwd  );
    			self::$verrou = true;
    		}
    		return self::$instance;
    	}
     
    	/* Destructeur */
    	public function __destruct()
    	{
    		$this->close();
    	}
     
    	public function close()
    	{
    		return NULL;
    	}
     
    	/* Une fonction publique*/
    	public function deleteField($table_name, $sql_condition, $limit = 1, $mode_admin = false)
    	{
     
            // Acces aux méthodes PDOStatement ainsi qu'aux méthodes locales de la classe
     
             $mon_bidule = $this->methode(parametre);
     
    	return $mon_bidule ;
    	}
     
    } /* fin classe */

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

Discussions similaires

  1. Comment récupérer le nom du fichier sans l'extension ?
    Par altahir007 dans le forum Langage
    Réponses: 16
    Dernier message: 13/11/2009, 13h20
  2. singleton, polymorphisme, et surcharge de fonction
    Par legend666 dans le forum C++
    Réponses: 11
    Dernier message: 14/11/2005, 09h27
  3. Réponses: 5
    Dernier message: 24/04/2003, 11h47
  4. Algo de tri, extension
    Par Mouse dans le forum Langage SQL
    Réponses: 5
    Dernier message: 27/02/2003, 00h14
  5. Réponses: 8
    Dernier message: 20/11/2002, 11h50

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