CLASSE PHP4 DE CONNEXION À UN SGBD

gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010 - 21 mai 2008 à 15:35
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010 - 11 juin 2008 à 13:47
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/46721-classe-php4-de-connexion-a-un-sgbd

gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
11 juin 2008 à 13:47
Merci, à tous de vos commentaire, c'est sympa de pouvoir confronter ses idées et c'est comme ça que l'on apprend.
A plus
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
11 juin 2008 à 12:16
Ca dépend de ce que tu appelles une factory...
Pour moi, c'est au minimum une méthode statique. Mais ça pourrait aussi être une classe statique.

$base = BASE::load (NOM, MDP, BASE, SERVEUR, SGBD);

La méthode statique load est une factory : c'est elle qui va instancier la bonne classe en fonction de ce que tu lui demandes.

"je suis en PHP5 mais le serveur est en PHP4"

T'as pas à avoir honte : je suis dans le même cas, au boulot (on choisit pas tout, et surtout, faire des mises à jours aussi importantes sur plusieurs serveurs en prod, ça nécessite de faire quelques tests, et pour ça, faut avoir du temps)
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
10 juin 2008 à 18:25
Je veux dire, le serveur est en PHP4, il va me rendre fou.
Tchao
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
10 juin 2008 à 18:20
Hello,
je pensais à une factory du type :(vue sur php.net)
class Exemple
{
// La méthode de paramètre d'usine
public static function factory($type)
{
if (include_once 'Drivers/' . $type . '.php') {
$classname = 'Driver_' . $type;
return new $classname;
} else {
throw new Exception ('Driver non trouvé');
}
}
}
Ce qui m'éviterai d'inclure les différentes classes dans mon fichier d'inclusion mais seulement la classe mère, elle même se chargeant de charger le driver du sgbd souhaité lors d'une instanciation.
Ouais, désolé je plane pour E_STRCIT mais c'est par ce qu'en local (je suis quand même pas tout à fait maso), je suis en PHP5 mais le serveur est en PHP5. Mais j'essaye de coder avec le moins de syntaxe obsolète possible... (je sais bonne blague pour du PHP4).
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
10 juin 2008 à 14:09
Salut,

"Mais par contre, autant utilisé une factory pour permettre le chargement à la volée de la sous-classe utilisé, non?'"
Ca ne revient pas à ça, c'est exactement ça... La méthode statique load est la factory de ta classe dans ton cas.

"Par contre appelée la méthode load de façon static alors qu'elle n'est pas déclarée static car PHP4, cela me fait une erreur E_STRICT sur PHP5"
Autant écrire une classe PHP4 et une classe PHP5... Quitte à utiliser PHP5, autant l'utiliser pour de vrai, plutôt que de se limiter à une utilisation archaïque.
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
10 juin 2008 à 11:38
Par contre appelée la méthode load de façon static alors qu'elle n'est pas déclarée static car PHP4, cela me fait une erreur E_STRICT sur PHP5 que je peux éliminer dans mon gestionaire d'erreur avec debug_backtrace par exemple, mais c'est peut-être pas très propre. Si t'as une idée, mais bon c'est pas très grave. Bye
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
10 juin 2008 à 11:34
Si je connais l'appel de résolution de porté, bien que je ne sois pas un expert. En fait, tu m'as convaincu il suffit de faire $base = BASE::load (NOM, MDP, BASE, SERVEUR, SGBD); et de modifier la constante SGBD en fonction de celui utilisé mais j'y avais pas réfléchi et je voulais pas devoir changer les appels à chaque script. Mais par contre, autant utilisé une factory pour permettre le chargement à la volée de la sous-classe utilisé, non?

Pour les trigger_error, je vais potasser tout çà, en tous cas merci des liens car ils sont bien utiles. Je t'avoue que je suis un peu léger niveau connaissance.

Si je peux me permettre une petite question, je ne vois pas trop la différence entre méthode à portée de classe et méthode privée?

Merci encore de tes remarques constructives et à plus
Utilisateur anonyme
9 juin 2008 à 19:06
Lut, ru dis que tu aimes les fonctions car pas besoin de passer par un constructeur. Il me semble que tu ne connais pas vraiment l'appel de résolution de porté - un tuto à cette adresse :
http://fr2.php.net/manual/fr/language.oop5.paamayim-nekudotayim.php

Tu peux faire des fonctions statiques appellées sans instancier la classe ce qui permet d'encapsuler dans des classes des fonctions indépendantes. L'avatage c'est que quand tu lis ton code c'est plus lisible, et tu sais où trouver la fonction. Les singleton fonctionnent comme ça - un exemple en php 4 : http://zefredz.frimouvy.org/dotclear/index.php?2007/02/18/160-forcer-un-singleton-en-php4

Un ptit commentaire pour la gestion des erreurs. Il serais préférable tu que généres tes erreurs à partir de la fonction trigger_error car elle est utilisée par le framework php - tu peux les logguer et bien plus. Du coup jettes un coup d'oeil sur http://fr2.php.net/manual/fr/function.set-error-handler.php, tu peux facilement faire un singleton gérant l'abstraction des erreurs générées par ta partie de code et les autres erreurs système. L'avantage est de centraliser la gestion des erreurs, voire même de la surcharger pour la spécialiser selon cas d'utilisation. Ca serait un réel plus par rapport à tout ce qui existe déjà.

Bonne continuation
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
9 juin 2008 à 14:45
Salut,
C'est vrai que j'aime bien le principe de la fonction car elle permet de ne pas avoir à modifier les appels aux constructeurs dans les différents scripts lors de la migration vers un autre SGBD. Pour la gestion de plusieurs connexions on peut alors modifier la constante par une variable. Puis, on peut toujours utiliser un patterns.
Par contre, je trouve ton exemple sympa puisqu'il permet d'obtenir une erreur si on instancie un objet d'une classe inexistante. Merci de vos remarques, je vais me pencher sur les design patterns.
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
4 juin 2008 à 23:47
ceci dit, ça n'enlève rien au principe du singleton suggéré par Akhenathon (entre autres choses); on peut juste le transformer en multiton. Mais bordel, 1 connexion, 1 instance...c'est un minimum syndical, certes...mais ne pas être limité à 1 connexion est vital.
Pour l'interfaçage je rejoins Akhe, c'est facile à moindre frais, même en PHP4. Et c'est bien plus élégant comme son exemple le montre.
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
4 juin 2008 à 23:43
Hello,

heu oui...travailler avec plusieurs connexions peut-être carrément nécessaire. Sans parler de différents serveurs (bien que ce soit aussi mon cas, comme pour Neige apparemment : synchroniser 2 serveurs DB, par exemple...), on peut aussi avoir un serveur, et plusieurs DB... et une connexion par DB avec chacune leurs droits (histoire d'éviter les truncate malheureux....).
Non, jouer avec plusieurs connexions n'est peut-être pas une habitude dans le dév amateur, mais c'est carrément une quasi obligation dans le dév pro.
Utilisateur anonyme
4 juin 2008 à 23:40
De manière générale t'as une classe gérant la connexion. Si elle ne sert à être instanciée qu'une seule fois, c'est un singleton, or là ce n'en est pas un (mais c'est pas vraiment le pb).

Tu développes en objet, donc tu dois avoir une approche objet donc une approche sur l'instanciation de ta classe. Dans ton modéle tu proposes une fonction, c'est pas forcément bon en POO.

Tu aurais très bien pu créer une classe de type proxy, exploser un peu plus ton modéle...brèf améliorer ton modèle objet. Je te conseille de consulter le tuto de Malalam sur les design patterns il explique tout ça et c'est réalisable en PHP4.

En tout cas dans l'état de ton code tu ne peux appeller qu'une seule fois la fonction de connexion et le type de base de données ne devrait pas être définit ainsi. Juste un exemple équivalent :

class BASE {
...
function load($base, $host 'localhost', $user 'root', $pwd = '', $type = 'mysql') {
$class = 'BASE_'.$type;
if (class_exists($class)) {
return new $class($user, $pwd, $base, $host);
} else {
// GENERER UNE ERREUR
}
}
...
}

et au niveau utilisation ça donnerais :

$dbMySQL = BASE::load('test', 'localhost', 'root', 'pwd', 'mysql');
$dbPostGRE = BASE::load('test', 'localhost', 'root', 'pwd', 'postgre');
...etc...

Bonne prog et a+,
akh
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
4 juin 2008 à 11:37
"je ne vois pas l'intérêt d'ouvrir plusieurs connexion différentes par script."

Des fois, on a besoin de se connecter à plusieurs serveurs, parce que le fournisseur d'une entreprise n'a pas forcément envie de partager son serveur et sa base de données avec tous ses clients. C'est qu'un exemple...
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
3 juin 2008 à 22:04
En fait define ("SGBD", "MySQL") permet de modifier le sgbd utilisé sans modifier tous les appels qui sont fais dans les différents srcripts. Donc, si tu veux utiliser PostgreSQL par exemple, tu modifie simplement dans la fonction define ("SGBD", "PostgreSQL")et tu cré bien entendu la classe fille Postgre. De plus, tu as raison, cela fait une erreur si tu essaye d'ouvrir deux connexions puisque la variable est déjà déclarée mais ce qui est plutôt utile je trouve car je ne vois pas l'intérêt d'ouvrir plusieurs connexion différentes par script. Pour trigger_error, tu as raison mais j'ai fais en fait d'autre fonction qui réalise cela si impossibilité de se connecter ou d'executer la requête, ce qui me permet de ne pas lever d'erreur dans tous les cas mais d'interoger le résultat des méthodes pour ne pas stopper le script dans mon cas car mes E_USER_ERROR le stoppe dans mon gestionaire d'erreur. Merci de tes remarques, je vais aller voir ton travail. A plus..
Utilisateur anonyme
1 juin 2008 à 14:14
Pour l'histoire d'abstraction j'ai essayé de monter un modèle plausible :
http://www.phpcs.com/tutoriaux/ABSTRACTION-PHP_845.aspx
Utilisateur anonyme
1 juin 2008 à 13:27
Y'a un truc qui me géne, c'est le define ("SGBD", "MySQL"); a la ligne 190. Il ne devrait pas se trouver dans une fonction car il n'aimerais pas s'executer plusieurs fois ...

Sinon ligne 33 / 34 tu pourrait mettre :
function connect($login, $motDePasse, $base, $serveur) { trigger_error('You class must define a connect function !', E_USER_ERROR); }
function exe ($requete) { trigger_error('You class must define a exe function !', E_USER_ERROR); }

Cela ressemblerais un peu plus à de l'abstraction au cas où la classe ne serais pas construite correctement. Le désavantage c'est que l'erreur serais visible qu'à l'utilisation des fonctions...
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
22 mai 2008 à 14:26
Tiens... J'avais jamais remarqué que PHP redonnait la main... parce que, comme toi, mes catch sont en fin de script.

Maintenant, si ce que Markus dit est équivoque, ce qu'il énonce reste quand même (à mon avis en tout cas) une règle de "best practice".
Il y a ce que permet PHP techniquement et ce qui fait qu'un code est "bien codé".
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
22 mai 2008 à 12:39
C'est pas la question : dans les faits, une exception redonne la main. Tout ce qui se trouve après le catch sera exécuté. On en revient à la même discussion ;-) Si ce cher Marcus estime qu'un catch doit se trouver en fin de script, pourquoi PHP rend-il la main après un catch...? Une erreur fatale ne rend pas la main, parce qu'on estime que PHp est devenu instable et que ce serait dangereux.
Dans le cas d'une exception, c'est différent... : on tombe sur un cas exceptionnel. Ce qui ne veut pas dire que tout doit s'arrêter : seulement le traitement que l'on essaye (d'où "try"). Je continue de penser que Marcus est équivoque dans ce qu'il dit, quand bien même dans les faits, mes catch sont généralement à la fin du script (j'ai rarement plus d'un traitement par script, en fait).
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
22 mai 2008 à 11:36
Salut,

"Les exceptions
ne terminent pas un script mais elles permettent un traitement particulier, non?"

Si. Une exception termine un script. Elle ne redonne pas la main et NE DOIT PAS servir à effectuer un traitement différent du site.
La règle numéro 2 énoncée par Markus Börger dans son document "SPL for the masses" dit :
"Never use exceptions for control flow"
http://somabo.de/talks/200504_php_quebec_spl_for_the_masses.pdf (page 38)
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
22 mai 2008 à 10:58
Je l'ai dit ce que je reprochais : pas grand chose au niveau du code, mais pas mal au niveau des fonctionnalités. Une classe se contentant uniquement d'envelopper des fonctions existantes, ça n'a pas vraiment d'intérêt; il faut essayer de pousser plus loin.
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
22 mai 2008 à 07:42
perso, PDO + multiton, et ca roule :)

sinon, son code, je ne vois pas trop ce que tu lui reproches malalam. Enfin pour un code en php4, je vois difficilement comment faire mieux. Ce design :
driverinterface (ou classe abstraite)
drivermysql <---- driverinterface
driverpostgre <---- driverinterface
connections (driverinterface)

c'est un classique

bon, sauf que la, concection est une fonction alors qu'en general, connections est soit un singleton soit un muliton, (mais pas toujours une factory)

sinon, renvoyer false, pour pouvoir faire un ===false, pour contourner les exceptions, c'est comme faire des monades. Et les monades sont des trucs que les gens font dans des langages propres pour eviter les Exceptions (Exception etant un effet de bord...)
Mais en php, on a pas l'habitude de se preoccuper des effets de bords (surtout dans une classe comme celle-ci), donc les monades n'ont pas trop leur place.
Bref, si tu pouvais utiliser les Exceptions, ca serait bien, mais si tu veux rester en php4, alors ca me semble une bonne solution...

Bref, faire du php4 en 2008, c'est mauvais, mais pour du php4, moi je trouve que cette classe tient debout.
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
21 mai 2008 à 23:57
Oui lol en effet, les gens le voient assez tard en général...quand ils le voient ;-)
PDO ne répond pas à tout. C'est pour ça que sur ce code, j'insistais sur l'originalité des fonctionnalités. Si on doit faire une classe d'abstraction DB, il faut proposer des fonctionnalités, des simplifications sympas, utiles, et originales. Sinon en effet, autant utiliser PDO.
cs_depression Messages postés 100 Date d'inscription mardi 7 novembre 2000 Statut Membre Dernière intervention 13 juillet 2009
21 mai 2008 à 23:46
@Malalam: (je viens de me rendre compte que ton pseudo est un palyndrôme)

En fait, depuis PDO justement, je ne vois plus l'intérêt des classes d'abstraction justement, c'est ce que je voulais dire...
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
21 mai 2008 à 22:28
Elle revoie bien des true/false, non?
en tout cas merci de ses explications.
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
21 mai 2008 à 22:03
@GR43 : ta classe n'est qu'une couche d'abstraction DB./..elle gère les erreurs DB. Dans le cadre d'une boutique avec prise de commande, ou d'un applicatif logistique... : l'applicatif gère les erreurs de l'abstraction DB et réagit en fonction. C'est plus facile avec les exceptions je suis d'accord. Totalement :-) Mais ça reste faisable en PHP4 en se contenant de renvoyer des true/false en fonctiopn de ce qu'il se passe. Et donc, en interceptant les erreurs de type warning, notice etc...donc en les masquant.
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
21 mai 2008 à 21:59
J'ai parlé de PHP 5 (en disant que j'étais d'accord avec toi, c'était sous-entendu lol), et PDO...c'est déhà uine abstraction, alors la réutiliser pour faire une surcouche, bof...mais s'en inspirer, un peu comme ADODB, ça oui :-) Mais bon, en PHP4 c'est moins facile déjà...
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
21 mai 2008 à 21:36
Il n'est pas lié à ma classe. Mais si je ne veux pas que les erreurs comme une indisponibilité du SGBD ne soient pas toujours prises en charge par mon gestionnaire, dans certains traitements comme la validation d'une commande par exemple, comment faire? (restore_error_handler, debug_backtrace(), variable globale..., n'y a t'il pas d'autres moyens plus propres comme la gestion des exceptions de php5) Les exceptions
ne terminent pas un script mais elles permettent un traitement particulier, non? Désolé de te prendre la tête des deux côtés (forum et sources).
cs_depression Messages postés 100 Date d'inscription mardi 7 novembre 2000 Statut Membre Dernière intervention 13 juillet 2009
21 mai 2008 à 21:31
Malalam, qu'est ce qu'il t'arrive?

Comment ça se fait que tu n'aies pas parlé de PHP5.1 et de PDO?

Je ne sais que dire...
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
21 mai 2008 à 20:29
Je voulais dire pour les erreurs que parfois tu mets un @ (qui masque l'erreur, et tu peux donc n'avoir QUE ton gestionnaire en action), parfois pas.
Sinon, un vrai gestionnaire d'erreur personnalisée ferait l'affaire mais il ne doit pas être lié à ta classe. Il doit être global dans ce cas, donc c'est une autre source.
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
21 mai 2008 à 20:21
Merci pour vos commentaires.

Pour le php4 je n'est pas le choix vu le serveur.
Pour le
tu es dur car il y en un sur 2. C'est un de trop c'est vrai. Par contre pour le reste tu as tout à fait raison et je m'y attèle de ce pas. Je voulais juste savoir si je n'avais pas fait d'erreur de syntaxe car je débute en POO et PHP4 c'est un peu la m...
J'aurrai peut être dû la poster en forum, désolé.

Pour les erreurs avec une gestion personnalisée en PHP4, est on obligé de les avoirs, à part en modifiant les E_WARNING ou avec un debug_backtrace() dans la fonction car les @ ne suffisent pas ou encore en stoppant temporairement la gestion perso? Je ne vois comment faire autrement car pas d'exception.

Merci encore.
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
21 mai 2008 à 19:39
Hello,

je suis embêté pour commenter ton code. Je pense la même chose que Dépression. Déjà.
Ensuite, il est vraiment très basique. Je pourrais louer le débutant qui fait de l'abstraction en php4. La base est bonne. Il y a pas mal de problèmes quand même.
Bon...vaguement, je ne vais pas m'éterniser :
- tu manques de constance dans l'écriture du code : choisis entre le français et l'anglais!
- ton code balancera les erreurs PHP de toute manière selon l'error_reporting, dans certains cas. Pas dans d'autres. Cela rejoint le manque de constance.
- avec juste un
tu parviens à nous imposer du html 3.2 à l'heure du xhtml...c'est quand même dommage. C'était pas la mort d'écrire
au lieu de
...
- mysql_pconnect()...et si je ne veux pas de connexion persistante, je fais quoi...? Je modifie ta classe? A quoi bon faire de l'objet dans ce cas ? Une classe d'abstraction DB doit au moins donner un choix. Tu n'en donnes aucun.
- ta classe ne fait qu'envelopper des fonctions existantes : elle ne propose rien de nouveau, ni aucune facilité. Si au moins tu nous proposais différentes DB, mais là en l'occurence, non, il faut les coder soi-même. Dans ce cas, tu aurais pu au moins donner quelques fonctionnalités nouvelles, nous permettre de faire en un appel ce qui prend plusieurs lignes de code sans classe (renvoyer la clef primaire d'une table par exemple ? Chercher si une table existe ? Une bdd ? Un champ ? etc...).

Bref...ce n'est pas MAL codé. C'est propre, ça va. C'est correct, quoi. Mais ça n'apporte vraiment rien. Pas même à toi, à part le plaisir de le coder et du coup de t'améliorer. Mais à nous...? Rien.
Tu devrais approfondir, vraiment beaucoup. Et même si ton but n'est que de t'améliorer et d'avoir des critiques : vas plus loin...parce que là le code est tellement basique qu'il n'y a pas grand chose à en dire : c'est ok. Voilà. En même temps, tu n'as pas pris de risque.
cs_depression Messages postés 100 Date d'inscription mardi 7 novembre 2000 Statut Membre Dernière intervention 13 juillet 2009
21 mai 2008 à 15:41
Je te rappelle que PHP4 est mort...
gr43 Messages postés 95 Date d'inscription mardi 20 mai 2008 Statut Membre Dernière intervention 8 septembre 2010
21 mai 2008 à 15:35
N'hésiter pas à corriger mes erreurs. Merci