8796 sujets

Développement web côté serveur, CMS

Bonjour,

Je travaille depuis peu en php et mysql. Sur les bons conseils d'un ami informaticien, je passe en PDO pour gérer les liens vers ma BDD.

J'ai un souci dont les forums parlent peu, et que le manuel PHP ne semble pas évoquer... Smiley bawling

J'utilise un modèle MVC - et pour faire simple, si je ne mets pas les informations de connexion à la BDD directement dans la fonction (qui se trouve dans un modèle) - au lieu de la mettre dans un contrôleur ou dans un fichier à part par exemple - il refuse d'appliquer la méthode demandée en me renvoyant l'erreur call to member function on a non-object

J'espère que je suis assez clair Smiley confus - merci de votre aide.

ci dessous la portion de code que je suis censé mettre dans CHAQUE fonction qui fera appel à la base...(vous comprendrez je pense que ça peut devenir un peu lourd à gérer... Smiley fache
[code=php] 
$PARAM_hote='10.111.XXX.XX'; 
$PARAM_port= '3306';
$PARAM_nom_bd= 'xxxxxxxxxxxxxxx-basev2';
$DSN = 'mysql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd;
$USER = "xxxxxxxxxx"; // nom d'utilisateur pour se connecter
$PWD = "xxxxxxxxx"; // mot de passe de l'utilisateur pour se connecter
$connexion = new PDO($DSN, $USER, $PWD);
Salut,

Tu peux peut être utiliser les superglobales pour te connecter à ta BDD, tu n'aurais alors plus que :
$connexion = new PDO($GLOBALS['DSN'], $GLOBALS['$USER'], $GLOBALS['$PWD']); 

à mettre pour que la connexion se fasse.

A moins que ton problème soit tout autre ^^
Merci pour ta réponse N-J.

L'idée est bonne, et je me suis débrouillé pour faire une solution qui revient en gros à ce que tu dis... Mais en fait, je cherche s'il existe une autre solution - je m'explique.

En gros je suis en modèle MVC, donc pour afficher une page, je vais aller chercher tout plein de pages php qui vont exécuter chacunes à leur tour tout plein de fonctions.

Beaucoup de ces feuilles vont devoir se connecter à la base et y collecter des données. Lorsque je fonctionnais avec mysql_query (par exemple), je n'avais qu'à ouvrir une fois la connexion à la base (ce que je faisais dans ma page principale (index.php) qui appelle les autres par la suite). Cela me permettait de ne pas avoir à rouvrir une connexion à chaque fois qu'une fonction a besoin d'aller piocher dans la base.

En utilisant PDO, je suis pour l'instant obligé de mettre une ligne au début de toutes mes fonction, pour créer une connexion à la base. Ce n'est pas bien joli, et ça doit sûrement être contre-productif.

Ce que j'aimerais, c'est ne déclarer ma connexion qu'une seule fois (dans ma page index.php) et que les fonctions appelées par cette page s'en servent directement, sans avoir à rouvrir une connexion.

Mais ça ne veut pas fonctionner comme ça.

Pour info, j'ai trouvé une piste sur le site PHP manual qui indique qu'on peut spécifier que la connexion reste ouverte même après l'exécution du script - je l'utilise, mais ça ne fait aucune différence :

 new PDO($DSN, $USER, $PWD, array(PDO::ATTR_PERSISTENT => true)


Voilou, si vous avez des idées Smiley biggrin
C'est une bonne solution, mais laisser ouverte ta connexion à la BDD te posera peut être des problèmes quand il y aura beaucoup de visiteurs en même temps... Ou peut être pas, j'ai utilisé aussi PDO mais c'était pour un intranet donc la question ne se posait pas...
Bonjour,

La solution la plus élégante (enfin selon moi) passe par l'utilisation du pattern singleton

Ce qui donne un truc du genre :

class DataBase {
 
    private static $instance;
 
    private function __construct ()
    {
        $PARAM_hote='10.111.XXX.XX';  
        $PARAM_port= '3306'; 
        $PARAM_nom_bd= 'xxxxxxxxxxxxxxx-basev2'; 
        $DSN = 'mysql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd; 
        $USER = "xxxxxxxxxx"; // nom d'utilisateur pour se connecter 
        $PWD = "xxxxxxxxx"; // mot de passe de l'utilisateur pour se connecter 
        parent::__construct($DSN, $USER, $PWD); 
    }
 
    public static function getInstance ()
    {
        if (!(self::$instance instanceof self))
            self::$instance = new self();
 
        return self::$instance;
    }
}


Et pour chaque utilisation (par ex une requête)

DataBase::getInstance()->query();


Ainsi la connexion a la base de donnée est faite une fois a un seul endroit et reste accessible partout.
Modifié par lepideble (16 Jul 2009 - 15:58)
Le singleton est l'idéal techniquement.

Sinon tu peux aussi placer l'instance de ta connexion dans une variable Globale, ou bien une simple variable que tu passe en paramètre à toute tes fonctions qui en ont besoin.
Merci pour vos réponses.

Pour info, je n'ai pas encore pris le temps de faire un singleton - mais je vais essayer ça dès que j'aurais un peu plus de temps.
QUant à la variable globale, j'avais essayé de faire ça mais ça ne voulait pas fonctionner. Il me renvoyait toujours l'erreur "member function on a non object".

Merci encore Smiley cligne
As-tu redéclaré ta variable dans ta fonction ?
$nom = "Pierre";//Variable globale
function afficheNom(){
    echo $nom; //Cette ligne n'affiche rien à l'écran
    global $nom; //rend la variable globale $nom accessible
    echo $nom; //Affiche Pierre
}
bonjour

Si tu utilises une construction MVC , tes fonctions doivent dépendre d'un controlleur.
Tu dois pouvoir utiliser un objet $db tel quel à partir de tes fonctions.

Pour cela, chaque controlleur a besoin d'accéder à cette valeur!
Pour n'avoir à l'initialiser qu'a un seul endroit , je pense que le mieux serait une classe "générique" qui initialise cet objet $db.

Dans cette classe "GlobalControlerAction" , tu peux y mettre une fonction init() qui initialise cette variable (en utilisant un pattern Singleton ou non .... je suis pas convaincu de son utilité dans ce cas)

Chaque controlleur appelera cette fonction avec un parent::ini() par exemple
On peut envisager de passer directement par le contructeur.

Sinon le plus important est la préparation de tes requetes ou prepared statment.
Le plus de ressources consommées sont les aller-retour entre les 2 serveurs (mysql et apache en génral) plutot que le contrôle d'une instance unique d'acces à cette base.

Ce que tu peux prévoir (toujours dans une optique MVC) c'est d'ouvrir la connection dans ton "bootstrap" (ou front controller) (le point d'entrée pour tout utilisateur).
Une fois ta connection établie( ne pas oublier un try catch) tu peux la propager ou mieux la passer à un registre d'objet (Registry pattern) qui évite de passer par les globals.

voilà quelques pistes en espérant ne pas avoir été trop "technique".
Merci à tous pour toutes ces pistes.
Je réussi à avancer avec le singleton pour le moment, et je vais m'en tenir à ca pour pouvoir terminer une V0.1 du site.
Je passerai du temps à explorer les dernières pistes une fois que le site sera fonctionnel, pour envisager un peu son optimisation.

Encore merci à tous.