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

Langage PHP Discussion :

Porté de la variable d'instanciation d'un objet PDO


Sujet :

Langage PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    48
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 48
    Points : 59
    Points
    59
    Par défaut Porté de la variable d'instanciation d'un objet PDO
    Bonjour

    Je suis entrain de me remettre au PHP et au passage j'en profite pour dépoussiéré mes connaissances. Ne connaissant pas trop PDO, je m'exerce à bien l'utilisé et j'ai un petit soucis.

    J'ai deux fonctions: la première pour me connecter à ma BDD

    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
     
    function connectBdd()
    		{
    			try
    			{
    				$connexion = new PDO('mysql:host=localhost;dbname=basetest', 'root', '') ;
    				$connexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
    				$connexion->exec('SET NAMES utf8');
    			}
    			catch (Exception $e)
    			{
    				echo 'Erreur : '.$e->getMessage().'<br />';
    				echo 'N° : '.$e->getCode();
    				die();
    			}
    			return $connexion;
    		}
    une deuxième pour récupérer une valeur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function retourneValeur($id)
    		{
    			//$bdd = connectbdd();			
    			$reponse = $bdd->query('SELECT * FROM test WHERE id='.$id );
    			$donnees = $reponse->fetch(PDO::FETCH_ASSOC);
    			return $donnees['nom'];
    		}
    Avant avec mysqli, je mettais ma fonction pour me connecter à ma base, ensuite, je pouvais faire des requêtes dans le reste de mon script sans problème.

    j'aurai pu faire avec mysql:

    fonction connectbdd(), pour me connecter à la BDD
    placer dans la variable $var la valeur de retour de la fonction retourneValeur()

    Si je suis cette logique avec PDO, ça donne ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $bdd = connectbdd();
    $var = retourneValeur(2);
    echo $var;
    Pour que ça fonctionne je suis obligé de mettre l'appel à la fonction $bdd = connectBdd(); , dans la fonction retourneValeur().

    Ca fonctionne donc c'est déjà ça , mais si je dois utiliser plusieurs fonctions récupérant ou insérant des données dans la BDD, je dois à chaque fois utiliser la fonction de connexion.

    Peut instancier la connexion grâce à une fonction qu'une seule fois dans la page du script?

    Ma façon de faire n'est peut être pas correct, PDO s'utilise peut être différemment?

    Merci d'avance, pour quelques explications qui m'aideront à mieux utilise PDO

  2. #2
    Membre émérite
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Points : 2 446
    Points
    2 446
    Par défaut
    Peut instancier la connexion grâce à une fonction qu'une seule fois dans la page du script?
    oui même je peux te le recommander. Généralement on met $connexion dans une variable (ou un attribut d'une classe) pis on l'initialise au démarage de la page pis on n'y touche plus jusqu'à la fin du script.

    apres soit tu le passe $connexion dans tes fonctions qui appellent la db, méthode naïve, soit tu décretes que tu définies $connexion en dehors de toute fonction (cad dans l'espace global) et tu demandes explicitement dans une fonction utilisatrice de la base de donnée de confondre $connexion définie localement avec la variable $connexion définie globalement. Tu utilises alors le mot clé global.

    je pense que ceci n'est pas spécifique à PDO
    PHP fait nativement la validation d'adresse électronique .
    Celui qui a inventé mysql_connect(...) or die() est déjà mort plusieurs fois.

    Utilisez le bouton résolu!

  3. #3
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Ouais en même temps une variable globale pour faire une connexion, c'est moyennement élégant. Perso je préfère une méthode statique pour pouvoir appeler la fonction de connexion autant de fois que je le souhaite tout en ne l'instanciant qu'une seule fois.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    48
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 48
    Points : 59
    Points
    59
    Par défaut
    Bonjour

    tout d'abord merci d'avoir pris le temps de me répondre. je m'aperçois que tout qu'a cause de tout ce temps passé sans manier PHP, je suis rouillé.

    Avant avec mysql j'aurai écrit ce code et il aurait fonctionné:

    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
    <?php
    function dbConnect()
    {
    	mysql_connect('localhost', 'root','');
    	mysql_select_db('basetest');
    }
     
    function retourneValeur($id)
    {
    	$requete = mysql_query('SELECT * FROM test WHERE id='.$id );
    	$resultat = mysql_fetch_assoc($requete);
    	return $resultat['nom'];
    }
    dbConnect();
    $var = retourneValeur(1);
    echo $var;
    ?>
    Si je suis cette logique avec PDO voir exemple de mon premier post ça ne fonctionne pas, il me faut mettre l'appel de la fonction de connexion dans ma fonction retourneValeur(). Ca fonctionne mais ça ne me parait pas satisfaisant.

    J'ai pensé à mettre global à ma variable d'instance de PDO, je dois pas être doué ça fonctionne pas.

    Etendre PDO dans un singleton je connais mais je veux rester au plus simple, je mets la POO de coté pour cet exercice.

    Après réflexions et quelques essais, j'ai trouvé une autre solution, la voici:

    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
    <?php
    Function connectBdd()
    {
    	try
    	{
    		$connexion = new PDO('mysql:host=localhost;dbname=basetest', 'root', '') ;
    		$connexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
    		$connexion->exec('SET NAMES utf8');
    	}
    	catch (Exception $e)
    	{
    		echo 'Erreur : '.$e->getMessage().'<br />';
    		echo 'N° : '.$e->getCode();
    		die();
    	}
    	return $connexion;		
    }
     
    function retourneValeur($id,$bdd)
    {
    	//$bdd = connectbdd();			
    	$reponse = $bdd->query('SELECT * FROM test WHERE id='.$id );
    	$donnees = $reponse->fetch(PDO::FETCH_ASSOC);
    	return $donnees['nom'];
    }
     
    $bdd = connectbdd();
    $var = retourneValeur(2, $bdd);
    echo $var;
    ?>
    Vu que le problème en fait c'est une histoire de porté de variable, en passant en paramètre, ma variable d'instance de PDO à ma fonction retourneValeur, ça fonctionne, c'est déjà mieux que ma 1ere solution, mais ça me laisse encore une impression de crade.

    A part la solution global y a t'il d'autres possibilités?

  5. #5
    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

    Il faudrait que tu évite de tirer une mauvaise conclusion dans cette affaire, et du coup te fâcher avec la POO (PDO entre autre) alors que ça na pas de rapport directe.


    Dans le fond, c'est l'inverse.
    Faut savoir qu'avec les fonctions mysql_*, donc comme tu faisais anciennement, ceci offrait effectivement un certain confort, car lorsqu'on faisait une connexion, MySQL conservait en mémoire cette connexion.
    Au bout, un simple appel à mysql_query() faisait en quelque sorte que l'on reprenait la même connexion.
    Il fallait juste éviter de fermer (mysql_close) la connexion pour justement éviter de reconnecter.

    D'ailleurs, regarde ton ancien code, dans la fonction retourneValeur($id), nulle part tu fait allusion à une variable liée à une connexion.
    Il n'y a aucun problème de portée à ce niveau par ce qu'il n'y a pas de référence à aucune variable de connexion.
    Par contre, si lors d'un appel à cette fonction $id existe mais n'est pas "passé" en argument dans la fonction, là cette fois tu auras un problème de portée sur cette variable $id, exactement la même que tu rencontre actuellement avec $bdd.


    Actuellement, avec PDO on ne retrouve pas cette fonctionnalité là, ce confort de connexion conservée en permanence.
    Au bout, tu ne fait que rencontrer un problème de portée qui est exactement la même dans n'importe quelle fonction, la même qu'il y a pour $id.
    Par défaut, que ce soit dans une fonction ou une méthode de classe, une variable a une portée locale, donc uniquement dans la fonction.

    Dis toi que finalement il n'y a rien d'extraordinaire, et ce n'est pas du tout lié à la POO ou PDO, tu ne fais que revenir dans un contexte normal.
    C'est avant qui n'était pas si normal que ça.


    Il y a plusieurs solutions pour résoudre cela :
    1/ Soit transmettre la variable Objet $bdd en paramètre, comme actuellement.
    2/ Soit déclarer $bdd en global dans la fonction.
    3/ Soit créer une classe PDO dérivée, avec une méthode static qui retournera un Objet PDO, genre MyPDO::getInstance() qui sera à faire dans la fonction.

    Il peut en avoir d'autres, mais c'est souvent ces 3 là qui sont retenues.

    A titre personnel, j'ai un petit penchant pour la 3ème, appel à une méthode statique.
    De même que la solution "crade" comme tu dis, ce serait plutôt la 2ème, en global (sans vouloir blesser qui que ce soit).
    La 1ère n'est pas moche, les choses peuvent très bien se concevoir ainsi.


    Prend le temps de faire des recherche sur le Net (le forum PDO entre autre) avec des mots genre PDO singleton.
    Même si un singleton ne s'impose pas, c'est tout de même très souvent la solution choisie.
    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]

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    48
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 48
    Points : 59
    Points
    59
    Par défaut
    Bonjour RunCodePhp et merci pour ton intervention très intéressante.

    Je n'ai nullement envie de me fâcher avec la POO, au contraire c'est un paradigme qui suscite chez moi un intérêt certain. Le modèle objet de PHP 4, ne m'avais pas vraiment donné envie de m'y attarder, mais celui de PHP 5 c'est autre chose.

    En écrivant ce topic ma démarche est d'être dans les bonnes pratiques, PHP est un langage qui évolue et je tiens à suivre autant que possible son évolution. Ne pas avoir écris de code pendant plus d'un an a créé pas mal de doute sur ce qu'il est bien de faire ou pas. PDO je ne l'ai pas beaucoup utilisé, du coups je me suis demandé si je faisais bien ou pas.

    Sinon pour la solution 3, je la connais, j'ai d'ailleurs ce genre de classe dans mes tiroirs.

    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
    <?php
    class pdos extends PDO {
     
    	private static $_instance;
     
    	public function __construct() {
    	}
     
    	/* Singleton */
    	public static function getInstance() {
     
    		if (!isset(self::$_instance)) {
     
    			try {
     
    				self::$_instance = new PDO('mysql:host='.DB_HOST.';dbname='.DB_BDD, DB_USER, DB_PASS);
     
    			} catch (PDOException $e) {
     
    				echo 'Erreur : '.$e->getMessage().'<br />';
    				echo 'N° : '.$e->getCode().'<br />';
    			}
    		} 
    		return self::$_instance; 
    	}
     
    	public function __clone()
    	{
    		throw new Exception('Je suis un singleton, ne me clonez pas !');
    	} 
    }
    ?>
    Maintenant que je sais que la méthode d'avant qui consistait à ouvrir une connexion et la laisser ouverte ne ce fait plus, je n'hésiterai pas à utiliser la solution 3, même dans un projet non-objet.

    Merci à tout ceux qui ont pris le temps de me répondre

  7. #7
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    tu peu regardé aussi du coté de Registry

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

Discussions similaires

  1. Portée d'une variable dans une boucle FOR ?
    Par Neo41 dans le forum C++
    Réponses: 20
    Dernier message: 17/11/2006, 11h14
  2. [XSLT] pb portée d'une variable
    Par NPortmann dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 23/05/2006, 15h53
  3. Portée d'une variable globale
    Par Giill dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 27/12/2005, 10h13
  4. [MFC] Portée d'attributs/variables ?
    Par BaBeuH dans le forum MFC
    Réponses: 4
    Dernier message: 14/06/2005, 10h31
  5. [debutant][Portée] Déclaration de variable .....
    Par Slein dans le forum Langage
    Réponses: 4
    Dernier message: 07/05/2004, 10h43

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