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
* 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;
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:
* 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;
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 !
* 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;
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:
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:
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:fredchou@nospam.free.fr
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:
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
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 ...
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
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 :
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 :
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 :
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('@')])"
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 'onurb@xiludom.gro'.split('@')])"
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('@')])"
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']; } }
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('@')"
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'];
}
}
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 'onurb@xiludom.gro'.split('@').collect{|p|
p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
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('@')"
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 :
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('@')"
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 :
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 :
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('@')"
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('@')"
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 'onurb@xiludom.gro'.split('@').collect{|p|
p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
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('@')"
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']; } }
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:
"bruno modulix" <onurb@xiludom.gro> a écrit dans le message de news:
42a807b8$0$6074$626a14ce@news.free.fr...
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'];
}
}
"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']; } }