|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||
|
Membre du Club
![]() Inscription : février 2007 Messages : 117 ![]() |
Bonjour,
Voici la situation dans laquelle je suis, l'état de mon raisonnement et mes questions ... J'aimerai considérer chacune de mes tables comme étant des objets et donc, pour chacune de mes tables, créer une classe contenant une fonction pour le SELECT, une fonction pour le INSERT, etc. Bien entendu, mes tables sont relationnelles. Exemple : TABLE langue est composée des champs : - id - code - langue - statut TABLE statut est composée des champs : - id - statut Comme vous l'aurez comprit, le champ statut dans langue contient un ID renvoyant vers l'id de la table statut. Je n'ai par contre pas envie de trop lier mes 2 tables dans une seule et même classe. Ma réflexion était donc la suivante : - je crée une classe LANGUE avec une fonction SELECT qui fait (en gros) un SELECT * FROM langue et qui stocke le tout dans un array ; - je crée une classe STATUT avec une fonction SELECT qui fait (en gros) un SELECT * FROM statut et qui stocke également le tout dans un array ; - je crée une troisième classe avec une fonction qui effectuerai un "croisement" entre ces 2 tableaux pour permettre de générer un nouveau tableau qui donnerait comme résultat l'équivalent d'une requête comme celle-ci : Code :
1 FR Français OK 2 EN Anglais NOK 3 NL Néerlandais OK ... Mes questions : 1. est-ce que ma réflexion "orientée objet" vous semble cohérente ou est-il tout simplement préférable de faire, dans ma fonction SELECT de ma classe LANGUE, la query complète ? 2. si ma réflexion est correcte, est-il possible de générer ce "croisement" de requête ? 3. en travaillant de la sorte (en gros, faire une query globale et faire un tri ou un filtre éventuel sur les résultats par la suite) ; n'est-ce pas un risque de ralentir le site puisqu'on ne fait aucun filtre dans la requête SQL elle-même ? 4. avez-vous une meilleure idée :-) ? Merci d'avance, Olivier |
||
|
|
00
|
|
|
#2 |
|
Membre éprouvé
![]() Inscription : février 2005 Messages : 401 ![]() |
Question fort intéressante, je suis confronté au même dilemme chaque fois que je créé un nouveau site.
Une piste que j'ai peut être trouvé (mais pas encore exploitée à fond par manque de temps ) serait l'utilisation de requêtes écrites par un objet (voir le package Zend_Db_Select de Zend Framework). ça permettrait de détecter dans la méthode de chargement qu'on essaye de faire une jointure sur une autre table et qu'on a donc besoin de remplir des attributs supplémentaires. Bon dit comme ça ce n'est peut être pas très clair mais vu que c'est encore en réflexion dans ma tête j'arrive pas à faire mieux pour le moment |
|
|
00
|
|
|
#3 |
|
Membre du Club
![]() Inscription : février 2007 Messages : 117 ![]() |
Mais donc l'idée en POO est meilleure de ne pas inclure dans le SELECT de ma classe LANGUE des éléments de requête d'une autre table ... histoire de ne pas lier ces 2 tables ensemble et donc de permettre une modif de la structure des tables sans devoir passer dans chacune des classes ou peut-on tout de même le faire ?
Enoncé comme cela, ça me parait logique ... Mais je ne vois pas comment faire pour, au départ de 2 tableaux : - 1 contenant les infos de la table statut : ID STATUT 1 OK 2 NOK - 1 contenant les infos de la table langue ID CODE LANGUE STATUT 1 FR Français 1 2 EN Anglais 2 Obtenir un seul tableau faisant la jointure ... Et puis, toujours ce problème de performance DB ! Dans ces exemple, on fait un SELECT global sur des tables contenant peu d'info donc pas de souci ... mais que donnerait un SELECT global dans une table contenant des miliers de records ? Doit-on dans ce cas, prévoir x fonctions de SELECT différente dans mes classes pour prévoir les différentes logiques applicatives (tantôt, j'aurai besoin de faire un filtre sur le code langue, tantôt sur le statut, etc.) ? Désolé pour toutes ces questions, mais venant du monde "procédural" ... c'est un grand changement pour moi :-) |
|
|
00
|
|
|
#4 |
|
Membre éprouvé
![]() Inscription : février 2005 Messages : 401 ![]() |
Oui c'est sûr que pour faire quelque chose de parfait, les éléments de ta table2 n'auraient rien à faire dans la classe correspondant à ta table1.
J'avais fais quelque chose comme ça à une époque mais niveau performances j'explosais tout (pas dans le bon sens...) ![]() L'idée d'utiliser un composant tel que Zend_Db_Select pour l'écriture des requêtes permet justement de rendre celles-ci modulables. Ce qui peut déjà aider pour la réalisation de filtres simples. Ensuite pour l'histoire des jointures, il faudrait que ta table1 ait un moyen de connaitre le nom des attributs de la table2 ($table2->getColNames() ???). Comme ça si tu détectes une jointure sur la table2 dans ta requête, tu vas chercher la liste des attributs nécessaires automatiquement. Comme ça chaque classe conserve bien en son sein seulement ses attributs à elle et pas ceux des autres. Il faut juste qu'elle sache communiquer avec les autres pour leur demander des informations sur leur structure. C'est marrant dit comme ça ça parait super simple mais quand je vais rentrer chez moi ce soir et me mettre à coder un truc comme ça je suis sûr que je vais encore me poser 200 questions à la seconde |
|
|
00
|
|
|
#5 | ||||
|
Membre Expert
![]() ![]() Inscription : janvier 2004 Messages : 1 238 ![]() |
Zend_Db_Select a l'air d'avoir ses limites... j'ai du mal a voir comment générer quelque chose comme :
Code :
* Le parenthesage des conditions AND OR * Les clauses de jointures dans un OR Il est possible de faire un framework permettant de gérer tout ca... j'suis en train d'en faire un ^^ mais c'est chaud en effet. Une idée intéressante c'est le concept de RELATION entre les objets. 2 objets(=table) "liés" le sont au niveau structurel (par une contrainte dans la base) ou au niveau fonctionnel (dans l'esprit du developpeur) mais dans les deux cas, ce lien peut etre exprimé dans le code. Ainsi, il n'est pas necessaire d'indiquer explicitement la clause de jointure, on peut faire quelque chose comme : Code :
Code :
$aSelect->join($monObject2, $monObject1::RELATION_1_WITH_OBJECT2); Le framework peut alors ajouter automatiquement la clause de jointure. On peut aussi imaginer quelque chose comme : Code :
$aSelect->WhereAnd($monObject1, $monObject2, NOM_RELATION);
__________________
PHP : Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production) Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error()); Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable. Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/ |
||||
|
|
00
|
|
|
#6 |
|
Membre éprouvé
![]() Développeur Web Inscription : mars 2008 Messages : 439 ![]() |
je pense qu'avec une très bonne notion des fonctions de tableaux tu pourra arriver à tes fins très aisément
La création d'une classe abstraite qui sera décliner pour toute tes tables. une jointures de deux select ne se ferait qu'avec un array_intersect() par exemple
__________________
I don't know what will be used in the next world war, but the 4th will be fought with stones. - Albert Einstein Pour détourner un avion, il faut monter dedans - Frédéric beigbeder |
|
|
00
|
|
|
#7 |
|
Membre éprouvé
![]() Inscription : février 2005 Messages : 401 ![]() |
Oui ça je te l'accorde Zend_Db_Select a ses limites. D'ailleurs je ne l'utilise pas, j'ai mon truc perso pour ça (qui n'est pas forcément mieux mais plus adapté à mes besoins). Je l'ai juste donné à titre d'exemple vu qu'il est assez répandu et qu'il y a une bonne doc dessus pour expliquer.
Ensuite pour le reste on est d'accords, ta réflexion semble rejoindre la mienne dans le fond mais tu as eu plus de courage que moi et tu es plus rentré dans les détails Donc en gros si je comprend bien, tes objets seraient capables de fournir des informations sur la structure de leurs tables correspondantes (attributs, clé étrangères ...) et tu aurais un objet "SelectQuery" qui te monterait une requête à partir de ça. C'est ça ? L'idée me semble pas mal mais la question que je me pose c'est qu'est ce que va te retourner ton objet SelectQuery après son exécution ? Un objet "ligneTable1", un objet "ligneTable2" ? |
|
|
00
|
|
|
#8 |
|
Membre éprouvé
![]() Inscription : février 2005 Messages : 401 ![]() |
Une petite chose au passage : ce qu'on est en train d'essayer de faire ne correspond il pas tout simplement au design pattern "active record" ?
|
|
|
00
|
|
|
#9 |
|
Membre Expert
![]() ![]() Inscription : janvier 2004 Messages : 1 238 ![]() |
en fait j'ai des select spécialisés du genre (les classes sont générées automatiquement avec un meta fichier contenant le schema ;o) :
$aSelect = new SelectObject1(); $aSelect2 = new SelectObject2(); // cas "simple" $aSelect->whereAnd($aSelect->getChamp1(), OPERATEUR_EGAL, $aSelect2->getChamp1()); // join automatique $aSelect->whereAndJoin($aSelect2->getRelation1()); Pour ce qui est du type de retour, ca depend de la methode utilisée pour interroger la base. Ca peut etre un objet (completement ou partiellement chargé) Ca peut etre un tableau indexé (si les données du select proviennent de plusieurs tables, ou contiennent des count(), max(), etc...) Enfin rien ne m'empeche de "reconstruire" facilement un objet a partir du tableau indexé ensuite ;o) Les parentheses sont gérés par l'ajout de select : $aSelect = new SelectObject1(); $aSousSelect = new SelectObject1(); $aSousSelect->whereOr(..., ..., ...); // condition1 $aSousSelect->whereOr(..., ..., ...); // condition2 $aSelect->whereAnd(..., ..., ...); // condition3 $aSelect->whereAnd($aSousSelect); va générer WHERE condition3 AND (condition1 OR condition2) je ne connais pas le pattern "active record", faudrait que je me renseigne ;o) Edit : oui, c'est un peu ca (apres m'etre renseigné ^^)
__________________
PHP : Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production) Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error()); Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable. Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/ |
|
|
00
|
|
|
#10 |
|
Membre du Club
![]() Inscription : février 2007 Messages : 117 ![]() |
et par rapport au fait de faire une query globale et d'ensuite faire un tri dans le tableau ...
qu'en penser au niveau performance ? est-il préférable de créer des fonctions de SELECT différentes selon la logique applicative désirée ou peut-on imaginer taper dans un array, le résultat d'une query globale (genre : SELECT * FROM langue) et ensuite faire des recherches et des filtres dans le tableau ? merci encore :-) |
|
|
00
|
|
|
#11 | ||
|
Membre éprouvé
![]() Inscription : février 2005 Messages : 401 ![]() |
Comme je l'ai dis, un query object est bien utile pour faire ce genre de chose. Parce que tu peux très bien imaginer une méthode de chargement qui prend en paramètre des "parts de requête" contenant des instructions de filtre ou de tri.
Par exemple quelque chose dans le style : Code :
En tout cas tout charger dans un tableau et faire les filtres après je pense que c'est très très mal. Si tu as 10 enregistrements voire 1000 ça va, mais si tu as une base de données gigantesque ça va faire très mal
|
||
|
|
00
|
|
|
#12 | ||||
|
Membre du Club
![]() Inscription : février 2007 Messages : 117 ![]() |
Bon j'avoue, j'utilise quasi pas les tableaux et j'ai dur dur au début ...
j'ai ceci : Code :
Code :
Array ( [0] => 1 [id] => 1 [1] => FR [code] => FR [2] => Français [langue] => Français [3] => Y [defaut] => Y [4] => 1 [statut] => 1 ) Pq ai-je chaque fois les trucs en double ... j'ai donc [0] => 1 et ensuite [id] => 1 ... idem, j'ai d'abord [1] => FR et ensuite [code] => FR comment faire pour avoir uniquement le [id] => 1, [code] => FR, etc. ? merci |
||||
|
|
00
|
|
|
#13 | |||||
|
Membre Expert
![]() ![]() Inscription : janvier 2004 Messages : 1 238 ![]() |
Citation:
fetch_array renvoie 2 fois le resultat, une fois avec un index numérique, une fois avec un index correspondant au nom de la colonne. _fetch_assoc est mieux ;o) (uniquement le nom de la colonne) Code :
__________________
PHP : Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production) Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error()); Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable. Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/ |
|||||
|
|
00
|
|
|
#14 |
|
Membre éprouvé
![]() Inscription : février 2005 Messages : 401 ![]() |
Bon alors je vois carrément pas le lien entre ton bout de code et le sujet mais c'est pas grave
Remplace : mysql_fetch_array par mysql_fetch_assoc |
|
|
00
|
|
|
#15 | |||||
|
Expert Confirmé Sénior
![]() ![]() Inscription : mai 2004 Messages : 4 490 ![]() |
Citation:
Code :
__________________
FAQ XML ------------ « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser » Giacomo Leopardi |
|||||
|
|
00
|
|
|
#16 |
|
Membre du Club
![]() Inscription : février 2007 Messages : 117 ![]() |
Voila ...
Ce point est résolu pour ma part en tout cas ;-) J'ai développé 2 classes qui me permettent de gérer et de générer des requêtes SELECT de manière "automatisée" et surtout qui sont capables de prendre en compte la structure de ma DB. Un peu long à expliquer ici mais j'essayerai de prendre le temps un jour ;-) |
|
|
00
|
Copyright © 2000-2012 - www.developpez.com