Portée global de connexion

Mammouth du PHP | 568 Messages

06 juil. 2009, 10:27

Bonjour à tous,

J'ai un petit soucis avec le protée de ma connexion PDO.

j'utilise une classe db qui instancie une connexion via pdo à ma base, et je souhaite créer une classe utilisant cette connexion afin de faire des requêtes.

Ma classe utilisant PDO
<?php
	//require_once('library/config.php');
	
	class db {	
		/*** Declare instance ***/
		private static $instance = NULL;
	
		/**
		*
		* the constructor is set to private so
		* so nobody can create a new instance using new
		*
		*/
		private function __construct() { }
		
		/**
		*
		* Like the constructor, we make __clone private
		* so nobody can clone the instance
		*
		*/
		private function __clone(){	}
		
		/**
		*
		* Return DB instance or create intitial connection
		*
		* @return object (PDO)
		*
		* @access public
		*
		*/
		public static function getInstance() {		
			if(!self::$instance) {
				if(MODE_PERSISTANT) {
					//avec persistance
					self::$instance = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASSWORD, array(
							PDO::ATTR_PERSISTENT => true
					));
				} else {
					//sans persistance
					self::$instance = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASSWORD);
				}
				
				self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			}
			return self::$instance;
		}
	}
	
	try {
		$db = db::getInstance();
	} catch(PDOException $e) {
		if(DEBUG) {
			echo 'Erreur : '.$e->getMessage();	
		} else {
			echo "Une erreur est survenu lors de la connexion à la base de données.";
		}
		die();
	}
?>
Ma seconde class
<?php
	<?php
	require_once('config.php');
	require_once('db.class.php');
	
	class plateforme_logistique {
		
		private $plateforme_id;
		private $plateforme_nom;
		private $plateforme_adresse;
		private $plateforme_code_postal;
		private $plateforme_ville;
		private $plateforme_tel;
		private $plateforme_fax;
		private $plateforme_date_creation;
		private $plateforme_date_modification;
		
		private $error = array();
		
		public function __construct() {			
			$this->plateforme_id = NULL;
			$this->plateforme_nom = NULL;
			$this->plateforme_adresse = NULL;
			$this->plateforme_code_postal = NULL;
			$this->plateforme_ville = NULL;
			$this->plateforme_tel = NULL;
			$this->plateforme_fax = NULL;
			$this->set_date_creation();
			$this->plateforme_date_modification = NULL;
		}
		
		public function __destruct() {}
		
		public function __clone() {}
		
		public function set_id($plateforme_id) { $this->plateforme_id = $plateforme_id; }		
		public function set_nom($plateforme_nom) { $this->plateforme_nom = $plateforme_nom; }
		public function set_adresse($plateforme_adresse) { $this->plateforme_adresse = $plateforme_adresse; }
		public function set_code_postal($plateforme_code_postal) { $this->plateforme_code_postal = $plateforme_code_postal; }
		public function set_ville($plateforme_ville) { $this->plateforme_ville = $plateforme_ville; }
		public function set_tel($plateforme_tel) { $this->plateforme_tel = $plateforme_tel; }
		public function set_fax($plateforme_fax) { $this->plateforme_fax = $plateforme_fax; }
		public function set_date_creation() { $this->plateforme_date_creation = date("Y-m-d H:i:s"); }
		public function set_date_modification($plateforme_date_modification) { $this->plateforme_date_modification = $plateforme_date_modification; }
		
		public function insert() {
			//global $db;
			
			//query
			$sql = "INSERT INTO plateforme_logistique (plateforme_nom, plateforme_adresse, plateforme_code_postal, plateforme_ville, plateforme_tel, plateforme_fax) VALUES (:plateforme_nom, :plateforme_adresse, :plateforme_code_postal, :plateforme_ville, :plateforme_tel, :plateforme_fax);";					
			
			//prepare sql
			$stmt = $db->prepare($sql);
			
			//prepare param
			/*$stmt->bindParam(":plateforme_nom", $this->plateforme_nom, PDO::PARAM_STR);
			$stmt->bindParam(":plateforme_adresse", $this->plateforme_adresse, PDO::PARAM_STR);
			$stmt->bindParam(":plateforme_code_postal", $this->plateforme_code_postal, PDO::PARAM_STR, 5);
			$stmt->bindParam(":plateforme_ville", $this->plateforme_ville, PDO::PARAM_STR);
			$stmt->bindParam(":plateforme_tel", $this->plateforme_tel, PDO::PARAM_STR, 10);
			$stmt->bindParam(":plateforme_fax", $this->plateforme_fax, PDO::PARAM_STR, 10);
			$stmt->bindParam(":plateforme_date_creation", date("Y-m-d H:i:s"));
			
			//exec sql
			return $stmt->execute();*/
		}
		
		public function update() {
			//query
			$sql = "UPDATE plateforme_logistique SET 
				plateforme_nom = :plateforme_nom,
				plateforme_adresse = :plateforme_adresse,
				plateforme_code_postal = :plateforme_code_postal,
				plateforme_ville = :plateforme_ville,
				plateforme_tel = :plateforme_tel,
				plateforme_fax = :plateforme_fax 
				WHERE plateforme_id = :plateforme_id;";
			
			//prepare sql
			$stmt = $db->prepare($sql);
			$stmt->bindParam(":plateforme_id", $plateforme_id, PDO::PARAM_INT);
			$stmt->bindParam(":plateforme_nom", $plateforme_nom, PDO::PARAM_STR);
			$stmt->bindParam(":plateforme_adresse", $plateforme_adresse, PDO::PARAM_STR);
			$stmt->bindParam(":plateforme_code_postal", $plateforme_code_postal, PDO::PARAM_STR, 5);
			$stmt->bindParam(":plateforme_ville", $plateforme_ville, PDO::PARAM_STR);
			$stmt->bindParam(":plateforme_tel", $plateforme_tel, PDO::PARAM_STR, 10);
			$stmt->bindParam(":plateforme_fax", $plateforme_fax, PDO::PARAM_STR, 10);
			//exec sql
			$stmt->execute();
		}
		
		public function delete() {
			
		}
		
		public function get_liste() {
			
		}
	}
	
	$test = new plateforme_logistique();
	$test->set_nom("test");
	$test->set_adresse("adresse");
	$test->set_code_postal("01000");
	$test->set_ville("bourg");
	$test->set_tel("test");
	
	//var_dump($test);
	if($test->insert()) {
		echo "insert ok";
	} else {
		echo "insert pas ok";
	}
?>
Pour se faire, je suis obliger de déclarer ma connexion en global dans la méthode de ma classe afin d'y avoir accès et je trouve ça moyen...

Je déclare avec le code suivant à l'intérieur de ma méthode insert()
global $db;
Existe-il un moyen propre / différent de faire cela?

EDIT:

l'autre solution que j'ai trouvé est d'étendre ma seconde class avec la class db et de faire dans chaque méthode
$db = parent::getInstance();
Mais je ne sais pas si c'est mieux.

Eléphant du PHP | 217 Messages

06 juil. 2009, 12:58

Bonjour,
vous utilisez un singleton pour instancier votre classe db. il vous suffit de l'include puis d'appele votre instance quand vous en avez besoin : $db = db::getInstance();

Mammouth du PHP | 568 Messages

06 juil. 2009, 14:37

ok,

mais est-ce la meilleur solution...connu et reconnu?

Eléphant du PHP | 217 Messages

07 juil. 2009, 09:47

Bonjour,
c'est une solution parmis d'autres comme l'injection de la classe db dans la méthode par exemple function myMethod(db $db){}

C'est en tout cas plus propre qu'un global :)

ViPHP
AB
ViPHP | 5818 Messages

07 juil. 2009, 14:07

Bonjour,
c'est une solution parmis d'autres comme l'injection de la classe db dans la méthode par exemple function myMethod(db $db){}

C'est en tout cas plus propre qu'un global :)
++
Pas mieux. C'est le global qu'il faut éviter et les singletons sont souvent employés dans ce cas.

Mammouth du PHP | 568 Messages

07 juil. 2009, 16:47

Merci à vous.

Eléphanteau du PHP | 19 Messages

05 août 2009, 00:00

Existe-il un moyen propre / différent de faire cela?

EDIT:

l'autre solution que j'ai trouvé est d'étendre ma seconde class avec la class db et de faire dans chaque méthode
$db = parent::getInstance();
Mais je ne sais pas si c'est mieux.[/quote]
Personnellement, je préfère garder ma classe DB séparée, quitte à la stocker dans mes autres classes :
$this->db = database::getInstance;

Ainsi toutes mes classe y ont accès et je ne risque pas de surcharger une de mes méthodes database... :wink:
Sinon le global est une option fréquemment utilisée.
Celui qui recherche la vengeance devrait commencer par creuser 2 tomnes (Confucius)

Mammouth du PHP | 991 Messages

05 août 2009, 07:39

Le global rend le debug beaucoup plus compliqué ;p (Mais où est cette variable déjà .... 2000 lignes plus loins ah oui ici :))


Donc le singleton est une bonne solution
DevOps, Symfony4, Hoa

ViPHP
AB
ViPHP | 5818 Messages

05 août 2009, 09:35

Le global rend le debug beaucoup plus compliqué ;p (Mais où est cette variable déjà .... 2000 lignes plus loins ah oui ici :))


Donc le singleton est une bonne solution
Tu as raison d'insister, le singleton est une bien meilleure solution qu'un global et c'est très souple d'emploi donc tout à fait adapté :wink:

Un exemple basique
class connect_bdd {

		private static $instance;
			
			private function __construct() {
			
				require_once('fichier_des_donnees_de_connexion');
				mysql_select_db($database, $connection);	

			}
			
			public static function getInstance() {
			
				if(self::$instance == NULL) self::$instance = new connect_bdd;
			}	 
}

connect_bdd::getInstance();

Eléphant du PHP | 189 Messages

05 août 2009, 18:12

Salut à tous,

Je rebondis sur cette question car je me la suis posée aussi ( ici ).

L'idée du singleton est pas mal, mais que faire lorsque notre class d'accès a la base de donnée permet de se connecter à plusieurs base ?

L'idée tombe à l'eau (Une instance par base de donnée) et donc, l'idée de passer l'identifiant a la class peut être retenue ?

Est-ce propre ? (Vu que je vois que vous parler tous du singleton )

Merci

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

05 août 2009, 19:15

Pour répondre à ce besoin, tout en gardant la souplesse du design pattern Singleton, il existe un autre design pattern : le Multiton.

En gros, tu gardes le principe du Singleton, mais en donnant un identifiant.

Voici un exemple codé :
class connect_bdd
{
	private static $instance = array();
                        
	private function __construct($db_name) 
	{
		require_once('fichier_des_donnees_de_connexion');
			
		// Permet de verifier que la base de donnees demandee existe
		if( !array_key_exists($db_name, $database) )
			throw new Exception('[connect_bdd] given database name "'.$db_name.'" is not configured');
			
		mysql_select_db($database[$db_name], $connection);        
	}
	
	public static function getInstance($db_name) 
	{
		// Si l'instance de connexion à la base de donnees n'existe pas, creation puis ajout à la liste des instances
		if( !array_key_exists($db_name, self::$instance) )
		{
			self::$instance = new connect_bdd($dbname);
		}
		
		return self::$instance[$db_name];
	}        
}

connect_bdd::getInstance('db1');
connect_bdd::getInstance('db2');
connect_bdd::getInstance('db1');
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Eléphant du PHP | 189 Messages

05 août 2009, 20:04

Merci beaucoup, j'ai répondu sur l'autre sujet..