OVH Cloud OVH Cloud

Ressource de connexion MySQL

20 réponses
Avatar
Frederic Rouchouze
Bonjour à tous,

Je me pose une question philosophique à propos des ressources de connexion
(renvoyées par la fonction mysql_connect() par exemple) :

Afin de programmer "proprement", dois-je passer systématiquement en argument
à mes créateurs de classes une ressource de connexion ?
Exemple :
$bdd=mysql_connect();
$truc=new truc($bdd);

Ou bien dois-je utiliser la possibilité de la fonction mysql_query() qui est
la suivante : "Si link_identifier n'est pas précisé, la dernière connexion
est utilisée" ?
Exemple :
mysql_connect();
$truc=new truc();

Question subsidiaire : Si la réponse à la première question est "oui",
comment organiser au mieux mon passage d'argument ?

Je m'explique : je serais tenté de mettre l'argument $bdd en dernier dans la
liste et en argument facultatif, au cas où je dérive ma classe "truc" et que
je ne veuille plus utiliser de base de données pour stocker les propriétés
de cet objet.
Exemple :
function truc($x, $y, $bdd=NULL)

Mais, dans ce cas, je ne peux pas utiliser le passage d'argument par
référence, qui me semble plus efficace pour transmettre ce type de donnée
(ressource). Mais peut-être me trompe-je...
Exemple :
function truc(&$bdd, $x, $y)

Merci de me donner votre avis,
--
Frédéric Rouchouze
mailto:fredchou@nospam.free.fr

10 réponses

1 2
Avatar
Frederic Rouchouze
* si tu veux creer un systeme de classes, il est tout de meme
un peu ennuyeux de se limiter à une seule base de données, meme
si les cas d'utilisation de plusieurs bases sont assez rares.
maintenant voici comment cela peut se concevoir :
Conclusion : on voit ici que les arguments internes de gestion de la base
sont encapsulés dans la classe. Il n'est meme point besoin de s'en
préoccuper. L'utiliser de la classe ne sait meme pas que ca existe.


Oui, c'est ce que j'ai fait en fait. Je ne passe pas en paramètre une
ressource de connexion mais une instance de ma classe BDD.
Mon soucis est donc de passer cette instance de classe BDD en paramètre à
une autre classe (dont les propriétés sont stockées en BDD).

J'aimerais pouvoir ne pas réécrire mon code existant qui utilise des appels
comme ceci :
Exemple :
$truc=new truc('a', 'b', 'c') // Au lieu de $truc=new truc($bdd,
'a', 'b', 'c')

Donc j'avais envie de code mon constructeur de la façon suivante :
Exemple :
class truc
{
var $bdd;

function truc($a, $b, $c, &$bdd=NULL)
{
if(is_null($bdd))
$this->bdd=new bdd();
else
$this->bdd=$bdd;
}
}

Mais le passage de paramètres par référence n'accepte pas de valeurs par
défaut, autrement dit le paramètre $bdd ne peut pas être optionnel. Ca
m'oblige à réécrire tout mon code existant en ajoutant le paramètre $bdd ou
bien de passer $bdd par valeur mais c'est pas très élégant !

Qu'en pensez-vous ?
--
Frédéric Rouchouze
mailto:

Avatar
Frederic Rouchouze
http://bugs.php.net/bug.php?id 175
function &GetInstance() {
static $instance;


Merci pour l'info ! Ca faisait un moment que je me demandais comment
implémenter un singleton en PHP... justement pour cette histoire de classe
BDD !
--
Frédéric Rouchouze
mailto:

Avatar
cleo
Je te dirais que c'est fonction de ton utilisation: si tu n'utilise qu'une
base, il n'y a aucun intérêt à t'inquiéter de la ressource de connexion vu
que tu utiliseras toujours la même.


Salut,
C'est sûrement pas un problème de base, mais de contexte transactionnel ou
de niveau d'isolation ...

--
Cléo

Avatar
Marc

Des namespaces ??? C'est à dire ?


ce sont des cloisons etanches qui permettent de creer des
espaces de noms. Et commes les variables et les noms de
classes sont "localisés", il n'y a pas (ou moins) de
collisions.

Mais sauf erreur de ma part, cela n'existe pas en php,
c'est pour cela que Pear possede des noms de classes
a ralonge :

Db_Mysql_XXX
Network_Socket_Reader
OS_Linux_Directory
Container_XML
Container_File_Flat

enfin c'est l'idée.

Avatar
bruno modulix
ftc wrote:
Honnêtement, je ne vois pas vraiment l'intérêt de faire de l'OO si c'est

pour mettre des globales.


Parce que PHP4 a de gros problèmes avec les static

, mettre une variable
en global est un moyen de pallier à ce défaut notament lorsqu'on a
besoin d'un singleton.


Oui, et il y a pas mal d'autres cas d'utilisations. En fait, c'est
propre (selon ma définition de "propre" of course) *si* c'est la
classe/l'objet qui gère ces globales, de façon transparente pour le code
client. Ce n'est alors qu'un détail d'implémentation.

Je réagissais au principe de classes dépendantes de globales "externes"
à la classe.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"


Avatar
bruno modulix
Frederic Rouchouze wrote:
http://bugs.php.net/bug.php?id 175
function &GetInstance() {
static $instance;



Merci pour l'info ! Ca faisait un moment que je me demandais comment
implémenter un singleton en PHP... justement pour cette histoire de classe
BDD !


En PHP4, le moyen le plus simple que j'ai trouvé est d'utiliser une
globale "masquée":


class MySingleton
{
function &getInstance() {
if ( ! isset($GLOBALS['MySingleton_intance']) ) {
$GLOBALS['MySingleton_intance'] = & new MySingleton();
}
return $GLOBALS['MySingleton_intance'];
}
}

$s1 =& MySingleton::getInstance();
$s2 =& MySingleton::getInstance();

Le code client ignore que l'instance est en fait une globale... Les deux
seules précautions : s'assurer qu'on n'a pas de conflit de nom pour la
globale masquée, et s'interdire d'y accéder directement.

--
bruno desthuilliers
ruby -e "print ''.split('@').collect{|p|
p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"


Avatar
bruno modulix
Marc wrote:

Des namespaces ??? C'est à dire ?



ce sont des cloisons etanches qui permettent de creer des
espaces de noms. Et commes les variables et les noms de
classes sont "localisés", il n'y a pas (ou moins) de
collisions.


Dans pas mal de langages, c'est proche de la notion de module, avec une
portée restreinte au module.

Mais sauf erreur de ma part, cela n'existe pas en php,
Non.


c'est pour cela que Pear possede des noms de classes
a ralonge :

Db_Mysql_XXX
Network_Socket_Reader
OS_Linux_Directory
Container_XML
Container_File_Flat

enfin c'est l'idée.


A vrai dire, les classes sont aussi un moyen de créer des espaces de
nommage en PHP:

class Utilitaire {
function util1(...) {}
function util2(...) {}
// etc
}

if (Utilitaire::util1(...)) {
Utilitaite::util2(...)
}

Mais (en PHP4 du moins), l'absence de variables de classe et
l'impossibilité de chainer les appels restreignent un peu l'utilité de
la chose...


--
bruno desthuilliers
ruby -e "print ''.split('@').collect{|p|
p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"


Avatar
bruno modulix
Frederic Rouchouze wrote:

(snip)

Oui, c'est ce que j'ai fait en fait. Je ne passe pas en paramètre une
ressource de connexion mais une instance de ma classe BDD.


Oui, mais tu la passe quand même en paramètre...

(snip)
J'aimerais pouvoir ne pas réécrire mon code existant qui utilise des appels
comme ceci :
Exemple :
$truc=new truc('a', 'b', 'c') // Au lieu de $truc=new truc($bdd,
'a', 'b', 'c')

Donc j'avais envie de code mon constructeur de la façon suivante :


(snip exemple où le constructeur de la classe Truc instancie la classe
bdd si une instance n'est pas passée en argument)

Mais le passage de paramètres par référence n'accepte pas de valeurs par
défaut, autrement dit le paramètre $bdd ne peut pas être optionnel.
(snip)


Là aussi, c'est plus un pb de conception objet qu'un pb PHP. Les
solutions "canoniques" sont les patterns Factory et/ou Singleton. Dans
ton cas, une combinaison des deux peut être une bonne solution:

// lib
function &db_factory {
require "config/db.php"; // contient $conf
$db_class = $conf['db_class'];
$key = "$db_class::instance";
if (! isset($GLOBALS[$key])) {
require_once "lib/{$db_class}.php";
$GLOBALS[$key] =& new $db_class($conf['connection_data']);
}
return $GLOBALS[$key'];
}

// classe de base si nécessaire
class AnyDb {
// ...
}

class MySQLdb extends AnyDb
{
// ...
}

class PgSQL extends AnyDb
{
// ...
}

// modele
class ModelObject
{
var $_db = NULL;

function ModelObject(...) {
$this->_db =& db_factory();
// ...
}
}

Cela t'évite de passer quoique ce soit en paramètre à tes objets. Les
deux seules dépendances restantes sont l'existence de la fonction
db_factory() (note que l'include du fichier définissant cette fonction
est lui-même paramétrable...) et le fait que cette fonction retourne un
objet ayant l'interface appropriée. Le reste est (à peu près)
transparent aussi bien pour les objets métier que pour le code utilisant
ces objets.

Mes 2 centimes.
--
bruno desthuilliers
ruby -e "print ''.split('@').collect{|p|
p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"

Avatar
Frederic Rouchouze
"bruno modulix" a écrit dans le message de news:
42a807b8$0$6074$
En PHP4, le moyen le plus simple que j'ai trouvé est d'utiliser une
globale "masquée":
class MySingleton
{
function &getInstance() {
if ( ! isset($GLOBALS['MySingleton_intance']) ) {
$GLOBALS['MySingleton_intance'] = & new MySingleton();
}
return $GLOBALS['MySingleton_intance'];
}
}

$s1 =& MySingleton::getInstance();
$s2 =& MySingleton::getInstance();


OK, je crois que je vais utiliser cette méthode. Mais y a-t-il un moyen
d'empêcher l'accès direct au constructeur de la classe ?

C'est à dire autoriser :

$truc=& truc::getInstance();

et interdire :

$truc=new truc();

Merci,
--
Frédéric Rouchouze
mailto:

Avatar
bruno modulix
Frederic Rouchouze wrote:
Mais y a-t-il un moyen
d'empêcher l'accès direct au constructeur de la classe ?

En PHP4, non PAQJS. A part la discipline, évidemment !-)


--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"

1 2