[Opened] Double foreach dans un template
Posted by Mindiell on 05/31/2011 11:22
Eh bien, ma requête me renvoit une liste type :
id parent nom 1 0 Parent_1 2 1 Enfant_2 3 1 Enfant_3 4 0 Parent_4 5 4 Enfant_5 6 0 Parent_6 7 7 Enfant_7
Je fais comment avec ça dans un template ? Parce que le foreach passe d'un enregistrement à l'autre, donc :
- j'ouvre le parent et je colle ses informations
- je dois vérifier qu'il y a des enfants pour ouvrir la liste des enfants
- je colle les enfants
- je referme la liste des enfants (uniquement s'il y en avait)
- je referme le parent, et j'ouvre un nouveau parent
etc...
C'est pas simple à faire avec jTpl pour moi. Je ne maitrise surement pas encore assez, alors je préfère avancer le reste (les tests unitaires, cf. mon autre post :) ). De toute façon, ça n'est pas hyper gourmand en ressources.
Mindiell
[Opened] Double foreach dans un template
Posted by laurentj on 06/02/2011 11:52
Comme je t'ai dit, tu te débrouilles pour ordonner selon l'id du parent (un order by dans ta requete quoi), avec une jointure sur la même table
SELECT P.id AS parent_id, P.nom as parent_nom, E.id as enfant_id, E.nom as enfant_nom FROM matable P LEFT JOIN matable E ON ( E.parent = P.id) WHERE P.parent = 0 ORDER BY P.id ASC
Tu obtient alors
parent_id parent_nom enfant_id enfant_nom 1 Parent_1 2 Enfant_2 1 Parent_1 3 Enfant_3 4 Parent_4 5 Enfant_5 6 Parent_6 null null 7 Parent_7 8 Enfant_8
à partir de là, quand tu parcours la liste, il suffit de détecter quand le parent change, et donc de générer le code qui concerne les parents, en plus du code des enfants.
{assign $currentparent=0} {foreach $objects as $object} {if $object->parent_id != $currentparent} <code> {if $currentparent != 0 } </ul> </div> </td></tr>
{/if}<tr class="row">
<td class="object"> <div class="informations"> <a href="#" class="title">{$object->parent_nom}</a> <span class="forum_description">{$object->description}</span> <span class="subobject">Enfants :</span><ul class="subforums"> {assign $currentparent=$object->parent_id}
{/if}
<li><a href="#"><span class="subobject">{$object->enfant_nom}</span></a></li>
{/foreach}
{if $currentparent != 0 }
</ul> </div> </td></tr>
{/if}
</code>C'est pas simple à faire avec jTpl pour moi
Ce n'est pas une question d'utilisation de jtpl. que tu utilises jtpl ou un simple script php ou autre, c'est la même problèmatique. C'est un problème d'algorithme et de connaissance sur le langage SQL.
Savoir programmer, c'est surtout savoir les bases de l'algorithmie, peu importe le langage.
De toute façon, ça n'est pas hyper gourmand en ressources.
Si, parce que tu dis que tu fais deux requêtes SQL, ca veut dire 2 fois plus de requêtes que ce que je préconise. C'est beaucoup un facteur 2.
En terme de complexité algorithmique (voir cours d'algo pour les histoires de complexité), avec ma solution, on a une complexité Ne (Ne= nombre d'enfant, Np = nombre de parents), donc en simplifiant, une complexité n.
Tu n'as pas précisé si c'est deux requêtes indépendantes (en tout), ou si c'est une deuxième requête faite pour chaque parent. Dans le premier cas on a donc une complexité Ne+Np (en simplifiant, une complexité n), mais tu solicites quand même deux fois plus le serveur sql. Je dirais presque 2n donc.
Dans le deuxième cas, la complexité explose : Np * Ne. En gros une complexité n^2. La différence est énorme. Multiplie ça par le nombre de visiteurs simultané, et tu arriveras beaucoup plus vite à un serveur saturé qu'avec une seule requete et une seule boucle. Surtout si c'est un forum si j'ai bien compris.
Au passage, ton code HTML n'est pas tip top. Faut éviter de mettre des span et des classes n'importe où et utiliser au mieux les sélecteurs css, en plus d'utiliser les balises html correctement (utiliser celles qui sont le plus adapté). En plus là je vois pas ce que viens faire ton tableau, vu qu'il n'y a qu'un colonne. Bref, tu pourrais très bien faire ceci avec la possibilité de le styler à l'identique :
{assign $currentparent=0} {foreach $objects as $object} {if $object->parent_id != $currentparent} <code> {if $currentparent != 0 } </ul></div>
{/if}<div class="row">
<h2><a href="#">{$object->parent_nom}</a></h2> <p>{$object->description}</p> <h3>Enfants :</h3> <ul> {assign $currentparent=$object->parent_id}
{/if}
<li><a href="#">{$object->enfant_nom}</a></li>
{/foreach} {if $currentparent != 0 }
</ul></div>
{/if}
</code>Code plus simple, plus light, donc se télécharge plus rapidement et prend moins de mémoire. Perf accrue.
[Opened] Double foreach dans un template
Posted by Mindiell on 06/03/2011 07:43
Ok, tu mets parents et enfants mélangés. J'y avais pensé, mais pour le moment j'ai mis en pause le bousin pour pouvoir étudier d'autres parties de Jelix, les tests unitaires et autres choses. En effet, l'algo est simple mais ne pas savoir ce qu'on peut faire avec jTpl freine un poil quand même.
Pour la table, j'ai bien plusieurs colonnes, et je compte bien allégé le code HTML, mais, là encore, les besoins d'optimisation ne sont pas ma priorité : j'apprends à utiliser Jelix ;)
Merci pour toutes ces informations en tout cas.
Mindiell