Requetes pré-existantes dans une abstraction sgbd

Résolu
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 - 30 janv. 2008 à 13:54
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 - 31 janv. 2008 à 23:01
Ceci est la suite de la discussion commencée à cette page : http://www.phpcs.com/codes/INTERFACE-DATABASE-CLASSE-MYSQL_45538.aspx

Mon exemple avec Top n'était peut-etre pas le meilleur, je dirai alors Offset de pgsql. Apres  bien sur la méthode des itérateurs semble intéressante (je la pratique aussi) dans ce cas là. Mais c'était en tant qu'exemple, pour un autre type de particularité de requete, je pense pas qu'on aura aussi des paliatifs en php.

Le framework CodeIgniter possède des classes de requetes directement (insert, update, delete, select, create, drop, show, ...), va faire un tour dans system>database>drivers>UNDRIVER>mysql_driver.php

J'ai pas regardé avec autant de précision les autres framework, mais du coup l'usage dans ton travail en est, je trouve facilité, car tu n'a qu'a appeler la fonction avec les éléments que tu veux (table, colonnes, valeurs, conditions) et hop ! :)

Sache que ton idée m'interesse, je viens juste de finir un systeme de Bdd abstraite ou j'intègre justement des classes de requetes avec des select et consort, donc j'aimerai bien ton point de vue histoire d'avoir la bonne (ou une meilleure) vision de la chose :)

15 réponses

malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
30 janv. 2008 à 21:00
T'as mal saisi, lol (en fait, je n'ai pas été assez loin dans mon exemple) :
tu n'as rien en procédural. En tous cas, aucune "requête". Ca on est d'accord, ce sont tes classes.
reprenons notre classe user.
J'ai une abstraction (ou une interfacen ou les deux...enfin, faisons simple) :
oAbstractUser qui implémente read, write, update, delete.
Et une méthode "connector" qui va chercher son driver...
Sans définition.
J'ai une classe usersql. Que fait-elle ? sa méthode select va faire une requête sql.
Une classe userxml. a méthode select va faire une requête Xpath
A côté (et au-dessus), j'ai une classe connector : on lui donne un driver, elle renvoie le bon objet.
Une class userManager qui prend un objet connector.
Tout ce que tu as à faire, c'est changer ton appel de départ : celui de ton userManager : tu changes juste le driver (ou l'objet connector).
Enfin bref, là c'est succint, mais est-ce que tu saisis le but de la manoeuvre ?
Tu peux même intercaler un objet userClient (je suis à court d'idées pour le nommage lol) qui prend une méthode select n'allant chercher que ce dont elle a besoin en fonction du module sur lequel on est (visualisation du récap des coordonnées d'un utilisateur selon sa demande), qui prend elle ses paramètres via un fichier de config (xml par exemple, définissant quelles infos aller chercher : son nom, son email, etc...) et qui, selon le "driver" va passer ces paramètres à la méthode select ou plutôt R du user* concerné (sql, xml...) qui lui va constuire ta requête.
Tu sais où tu en es facilement parce que tu sais sur quel module tu es, donc quel fichier de conf correspond, donc de quelles infos tu as besoin...
Mais en aucun cas ce ne sont les wrapper "connectors3 quyi se chargent de construire la requête en fonction de paramètres passés : parce que eux, ils sont génériques.
3
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
30 janv. 2008 à 21:17
oui

:-)
3
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
30 janv. 2008 à 20:22
Hello,

donc...
je suis sur CodeIgniter là.
J'ai maté la version mssql vu que c'est la bdd dont je me sers le plus :
    function _update($table, $values, $where)
    {
        foreach($values as $key => $val)
        {
            $valstr[] = $key." = ".$val;
        }
   
        return "UPDATE ".$this->_escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
    }
Franchement...lol...tu veux vraiment que je te dise ce que je pense de ça ?
On me donne une méthode qui va ne faire qu'ajouter UPDATE, SET et WHERE à une requête que je vais de toute manière devoir monter ? Et découper de façon à en extraire la table, les champs et valeurs (sachant qu'il m'incombe de placer les quotes là où il le faut, visiblement, parce que la méthode ne le fera pas à ma place, à moins que la méthode query de CI_DB_driver avec son paramètre $binds serve à ça, j'ai pas assez approfondi), et les conditions ?
Ok...
Imagines-toi : tu fais une grosse application en php. Tu utilises ce type de classe. Tu te prends déjà la tête pour faire les appels corrects avec les requêtes vu que tu dois les découper (je te parle d'une jolie application costaud...si tu veux un exemple, contacte moi par MP ou email, je te parlerai de ce que nous montons en ce moment au boulot).
Tout va bien, ton truc marche.
3 mois plus tard, tu dois modifier des trucs...sincèrement, tu penses que c'est plus lisible ce genre d'appels, que de voir ta requête en clair ?
Je préfère nettement un wrapper DB qui propose des méthodes utilitaires. Et du CRUD sur mes objets de travail (ma classe users par exemple, et pour simplifier largement).
C'est plus parlant un :
SELECT
usr_post.usr_post_nom, usr_post.usr_post_prenom,
usr_elec.usr_elec_email,
usr_fact.usr_fact_ville
FROM
users usr
INNER JOIN user_post usr_post ON usr_post.usr_id = usr.user_id
INNER JOIN user_elec usr_elec ON usr_elec.usr_id = usr.id
INNER JOIN user_fact usr_fact ON usr_fact.usr_id = usr.usr_id
WHEREusr.usr_id 666 AND usr.usr_dde 999

que d'essayer de piger ce que tu as fait comme requête en matant le contenu de variables $table, $where, $join etc que tu as passées à une méthode db::_select().
A mon avis.
Et le CRUD dans ce cas-là, pour moi se situe au niveau user, (ou dde, mais je ne te demande pas de comprendre ce que veut dire dde lol, disons que c'est un autre objet, c'est propre à mon projet du moment...), et là on peut se permettre d'avoir une méthode qui va chercher ce que l'on veut en automatisant tout ça (on va chercher les champs par exemple, on construits la requpete avec etc...pas de requête en clair) : parce que tu SAIS sur quel objet tu es, sur quelle méthode (c'est le R de CRUD mais spécialisé pour un type bien précis de module ; celui qui va chercher le résumé des coordonnées d'un utilisateur lié à une demande particulière, par exemple) tu es, et donc ce que tu vas chercher.
Mais si c'est un appel générique à une méthode _select() de ton wrapper de DB...bonjour le bordel. 3 jours pour développer...3 mois pour débugger, et tu ajoutes 1 semaine par modification que tu dois y apporter dans le futur.
Selon moi, ce n'est pas viable.

Sans parler du surcoup : quand je veux faire un select (ou un update, ou autre), je passe par au moins 2 méthodes, ou plus ? query, escape (voire bind d'abord), select? Ou dans l'autre sens (select, bind, escape, query) selon la méthodologie employée par le framework ? Côté perf, c'est pas top. Un wrapper de DB c'est déjà forcément assez lourd, sans qu'on y ajoute du poids inutilement.
Et là, la requête que je donne en exemple est simple : je te dis pas le bordel quand je fais des UPDATE... SET champ (SELECT MAX(champ) WHERE...bla bla) WHERE champ_autre (SELECT...INNER JOIN bla ON truc AND bidule...WHERE ... etc) ... etc. dans de tels cas (fréquents sur un gros projets), la méthode _update() va te sembler bien futile...voire même, va devenir un énorme fardeau. Pour ne pas dire boulet.

Maintenant, mettons qu'on n'utilise pas un tel framework pour un gros projet. Bah...querl intérêt de se trimballer un wrapper DB de ce framework qui a lui tout seul pèsera plus lourd que tout ton projet au complet ? ALors qu'un bête DB::query($sTaRequete) sera nettement plus lisible de toute manière ?

Nan, désolé, je ne suis pas du tout convaincu, tu l'auras compris :-)
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
30 janv. 2008 à 20:34
T'inquiete, j'avais compris que tu n'était pas convaincu, ce que je voulais, c'était ton argumentation, t'a toujours les bonnes paroles ! :)

Mais un truc me taraude, on avait parlé la derniere fois du niveau d'abstraction max que l'on peux faire, tu me disais de ne pas s'arreter à une bdd, mais aller encore plus haut (xml, doc, txt, et encore plein d'autres choses), ok, mais alors, si actuellement mon site est en mysql (avec ma couche abstraite qui va bien) et mes jolies requetes sont en SQL.

Si demain mon boss me dit "tu met tout en fichier doc" (bon d'accord c'est un fou, mais c'est pour l'exemple), va falloir tout modifier mon code qui utilisait mysql pour l'adapter. => Elles sont où tes belles paroles sur l'abstraction là ? :p

Ou alors j'avais mal saisi un truc ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
30 janv. 2008 à 21:13
En fait, si j'ai bien compris, userManager va prendre l'objet connector afin de savoir si userManager doit utiliser usersql ou userxml(par exemple connector aura une variable $driverName "sql" ou"xml") et userManager n'aura qu'a faire $sClassName="user".$this->SourceConnector->driverName; et ensuite un new $sClassName, qui instanciera un usersql ou userxml ? c'est correct comme ca ?
Et si tu change de driver, admettons doc, tu n'aura qu'à faire une classe userdoc

Juste un oui serait parfait :)
Un non avec plus de détails est aussi le bienvenu :)
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
30 janv. 2008 à 21:23
parfait :)
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
30 janv. 2008 à 21:44
une ptite illumination là : tu fait comment dans le cas ou tu veuille implémenter ActiveRecord ?
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
30 janv. 2008 à 23:24
L'implémentation concrète d'ActiveRecord doit alors se situer au niveau de tes classes spécifiques : ton user a sa propriété usr_nom, et usr_email par exemple.
Son implémentation "abstraite" se trouve dans ta classe DB. Pour schématiser encore, je raccourcis bcp. Ca reste le même principe.
C'est d'ailleurs la base de ce design pattern.
$user->usr_nom = 'codefalse';
$user->usr_email = 'codefalse@codefalse.com';
$user->write();
Et user::write() implémente ton active record en se servant du wrapper DB (ou du moins de ton connecteur, pour reprendre la complexité vue ci-dessus) et de son implémentation de l'ActiveRecord. Encore une fois, les données et la  structure de ces dernières viennent de ton objet spécialisé, ton connecteur spécialisé (usersql, userxml) se chargeant éventuellement de les transformer en "requête", pas de ton wrapper, qui lui fait juste son query().
En fait il faut scinder tout ça en petites classes spécialisées, ou utiliser une classe userTools éventuellement. Mais je préfère les petites classes spécvialisées utilisées comme des outils par la classe user principale.
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
30 janv. 2008 à 23:44
La question qui va te faire rire :
C'est quoi un wrapper, car j'ai regardé ca sur wikipedia :
http://fr.wikipedia.org/wiki/Wrapper_%28informatique%29

mais je suis pas sur de comprendre par rapport à ce que tu dit toi :/
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
31 janv. 2008 à 08:00
Une enveloppe : quelque chose qui enveloppe autre chose. En l'occurence ici je fais référence à une abstraction qui enveloppe de manière transparente l'attaque d'un connecteur. Aucun rapport avec la définition que tu as trouvé en effet :-) Mais c'est un terme relativement commun dans ce sens aussi.
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
31 janv. 2008 à 11:38
En fait dans ton cas ce serait une sorte de factory qui instancierai autant une bdd mysql qu'un fichier xml, en fonction du parametre donné (ou du fichier conf) ?
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
31 janv. 2008 à 19:24
En gros, oui, c'est le principe.
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
31 janv. 2008 à 22:04
Dit c'est quand que tu me prends dans ta boite ? ;)

Dit c'est quand que tu me fait un cours complet sur la poo ? :p
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
31 janv. 2008 à 22:13
Lol...qui sait ?
On est au complets là. Mais ça ne durera pas...(on est déjà débordés lol, alors qu'on a embauché il y a peu).
Quant au cours...heu...quand tu viendras bosser dans ma boîte ? :-)
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
31 janv. 2008 à 23:01
Pas soucis, de toute facon c'était pas vraiment sérieux.
Bien sur ce serait avec plaisir que de venir bosser dans ta boite (honnetement), mais là j'ai encore 3 ans d'école, donc bon ... :p
Peut-etre dans 3 ans ... si tu y es toujours ! :)

Quand aux cours, en effet ca peut-etre une solution ! :)

J'ai tant à apprendre !
0
Rejoignez-nous