SPIP-Contrib

SPIP-Contrib

عربي | Deutsch | English | Español | français | italiano | Nederlands

286 Plugins, 197 contribs sur SPIP-Zone, 178 visiteurs en ce moment

Accueil > Navigation > Tris hétérogénes > Boucles sans tables > Boucler sur un tableau, un compteur, les langues, une condition (...)

Boucler sur un tableau, un compteur, les langues, une condition ...

20 janvier 2006 – par piif – commentaires

4 votes

construction de boucles permettant de parcourir un tableau php, d’itérer sur un compteur, de faire une condition, et d’itérer sur les langues

Nota SPIP-Contrib : cette contribution existe dorénavant en plugin. En attendant la mise à jour de sa documentation cet article reste celui de référence
-  sur la Zone : http://trac.rezo.net/trac/spip-zone...

Mise à jour du 29/11/2005 : quelques debugs et améliorations

L’idée de ce package est de créer des boucles sur autre chose
que des tables sql. Il y a 4 exemples dans le zip :

  • boucle langues : permet d’itérer sur les langues spip
  • boucle for : permet de boucler en affectant #COMPTEUR_BOUCLE à
    des valeurs successives (le for de php en gros)
  • boucle tableau : permet d’itérer sur les clés/valeurs d’un tableau
  • boucle if : permet de faire un tour de boucle si une condition
    est vraie

Installation

le tar contient 9 fichiers : 4 .php à inclure depuis mes_fonctions
ou assimilé, 4 squelettes d’exemple et un mes_fonctions d’exemple.
il suffit de détarrer ça à la racine d’un spip 1.8.2 ou 1.9, de mettre un include des fichiers php dans mes_fonctions.php3 (voir le fichier mes_fonctions.exemple.php3) et d’appeler les exemples par des urls comme page.php?fond=testLangue

Attention : le code est relativement quick and dirty. Je ne
sais pas trop ce que ça donne si on utilise ces boucles avec des
trucs tordus, des critères de travers ou des imbrications à tiroirs.

La boucle langue

C’est la plus simple car elle n’accepte aucun critère (on verra
plus tard si y’a besoin).

Elle permet d’itérer sur les langues définies « actives » dans
l’interface privée, et peut servir, par exemple, à faire un menu
langue personnalisé (tout ça viens d’une discussion sur la liste).

L’exemple joint (testLangue.html) montre à peu près tout ce qu’on peut faire avec, c’est à dire pas grand chose :-)

<BOUCLE_l(LANGUES)>
<br>#LANGUE : [(#LANGUE|traduire_nom_langue)].
</BOUCLE_l>

Si on ajoute le critère {tout} la boucle prend toutes les langues définies, et pas seulement celles activées. Attention,
si la configuration de précise pas de langues, elles sont toutes
considérées actives.

Comment ça marche : il suffit de définir une fonction
boucle_LANGUES pour traiter ce type de boucle.
Comme il n’y a pas de table ’langues’, on ’truande’ le compilo en
définissant des entrées dans la variable ’tables_principales’, et en
spécifiant sa pseudo-existance dans table_des_tables.
Dans la fonction, il faut maintenant définir tout le code à générer
pour la boucle. À coups de copier/coller depuis les boucles existant
dans spip, on en déduit le bout de code qui va bien.

Pour le critère tout, c’est leparseur qui se débrouille et fixe
le champ « tout » à « true ». Selon cette valeur, on va chercher un
meta ou l’autre.

La boucle for

Celle là est un peu tordue, mais elle permet de voir comment utiliser
des critères. L’utilisation basique de cette boucle est la suivante :

<BOUCLE_f(FOR){debut=2}{fin=10}{par 2}>
<br>#COMPTEUR_BOUCLE
</BOUCLE_f>

Contrairement à une boucle for dans php, on n’a pas besoin de définir de variable d’itération puisque #COMPTEUR_BOUCLE joue ce rôle.
Attention cependant, dans cet exemple, à la fin #TOTAL_BOUCLE
vaut 10 (dernière valeur) et pas 5 (nombre de tours).

Si le critère « par » est inversé ({!par 2}), on va en descendant, de « fin » jusqu’à « debut ».

Comment ça marche : comme pour la boucle précédente, on défini
une pseudo table qui contient des champs debut, fin
pour que le phraseur ne râle pas quand il croise ces noms dans les critères.

Là ou ça se complique, c’est qu’il faut analyser les critères
pour récupérer la valeur de debut, fin. Pour ça, on
parcours le tableau criteres de la structure de boucle et on
cherche les entrées ayant ’=’ comme opérateur et l’une des trois
valeurs comme partie gauche.
Il suffit alors d’appeler la fonction calculer_liste sur la partie
droite pour récupérer le code à insérer dans le code de la boucle.
Ce qui est magique, c’est que ça marche tout seul pour un
debut=1 ou pour un
debut=[(#TOTO|machin{bidule})].5

Une tambouille à base de eval permettrait également de traiter un
debut=#TOTO+1, mais j’ai l’impression que ça complique
pas mal les choses, et je ne maîtrise pas les effets de bord.

Enfin, pour le critère « par », c’est une fonction critere_par
qui surcharge la fonction par défaut et la rappelle si on n’est pas
en train de traiter une boucle for.

La boucle tableau

Après le for, le foreach ! Il s’agit cette fois d’aller chercher un
tableau associatif php et d’itérer sur ses clés / valeurs.
Le tableau doit sortir d’un élément extérieur (via mes_fonctions
ou autre) ou venir de spip (table meta, tableau des tables et autres
structures internes).

Il y a 2 contraintes :

  • il faut que ce tableau soit global, puisque quand on interprète
    une boucle, c’est toujours depuis une fonction gérée par le compilo
  • on ne peut pas définir ce tableau dans un tag php du squelette
    puisque celui ci sera évalué après le code du squelette (par contre
    ça marcherait sûrement dans le tag évoqué sur la liste).

L’utilisation de base est la suivante :

<BOUCLE_t(TABLEAU){var=toto}>
<br>- #CLE => #VALEUR
</BOUCLE_t>
vide ...
<//B_t>

Le critère var doit contenir le nom de la variable, et les
balises CLE et VALEUR correspondent aux paires clé/valeur. Si le
tableau est vide ou n’existe pas, on n’entre pas dans la boucle et
la partie <//B_..> est donc prise à la place.

Si jamais la valeur d’une entrée de tableau est elle même un
tableau, on peut utiliser cette valeur comme variable d’une boucle imbriquée via un critère {valeur} (exactement comme
quand on utilise un critère id_rubrique pour lister les articles
d’une rubrique sortie d’une boucle englobante) :

<BOUCLE_t(TABLEAU){var=tables_principales}>
        <BR>- #CLE => #VALEUR
        <BOUCLE_tt(TABLEAU){valeur}>
                <BR>-- #CLE => #VALEUR
                <BOUCLE_ttt(TABLEAU){valeur}>
                        <BR>--- #CLE => #VALEUR
                </BOUCLE_ttt>
        </BOUCLE_tt>
</BOUCLE_t>

Ici, on sort les entrée de la table tables_principales dont
chaque valeur est elle-même un tableau de tableaux.

Pour aller chercher un élément de tableau directement, on
peut utiliser le critère cle, éventuellement en plusieurs
exemplaires :

<BOUCLE_t(TABLEAU){var=tables_principales}{cle=spip_tableau}{cle=field}>
<br>- #CLE => #VALEUR
</BOUCLE_t>

Ici, on sort donc directement le contenu de tables_principales['spip_tableau']['field']

Enfin, on peut utiliser le critère {fonction=toto()}
à la place du critère var afin d’itérer sur un tableau
retourné par une fonction.

Attention aux infos que vous allez chercher avec ça : si vous
listez le tableau auteur_session par exemple, vous allez mettre en
cache vos propres infos de session que les internautes suivants
récupéreront dans le cache. => mettre le délai à zéro dans ce cas.

comment ça marche : le code est très proche de celui de la
boucle for, à part qu’il y a un critère valeur qui permet de
récupérer le champ valeur de la boucle au dessus.
Là, il y aurait un point à améliorer car on ne peut pas trouver une
valeur de 2 boucles au dessus (je pensais pouvoir utiliser la
fonction index_pile, mais ça retourne une valeur de l’étage courant).

La boucle if

Je sens que celle-là, elle va être sujet à polémique :-)

Il s’agit d’évaluer une condition et de rentrer dans la boucle
ou pas selon sa valeur. Le tag <//B_..> peut alors
servir de partie ’else’.

Voici un exemple basique (et donc complètement pipo :-) :

<BOUCLE_a(ARTICLES){tout}>
 #ID_ARTICLE
 <BOUCLE_if(IF){condition #ID_ARTICLE > 1}>OUI</BOUCLE_if>NON<//B_if>
</BOUCLE_a>

(attention, la syntaxe a changé depuis la version précédente)

La condition peut contenir à peu près tout ce qu’on mettrait
dans un if php.

comment ça marche : comme les autres, sauf que cette fois, on
ne génère pas une boucle, mais un if.
La condition est récupérée comme les autres paramètres, sauf qu’en
plus on fait un eval dessus pour pouvoir évaluer les opérations au
lieu d’avoir simplement une chaîne contenant le texte de la condition.

La condition est parfois évaluée de façon exotique, il faut donc
généralement faire des tests et ne pas hésiter à regarder le code
généré pour comprendre pourquoi un if ne se comporte pas comme prévu.
Par exemple, je suis tombé sur des cas ou un
#MACHIN==truc ne marchait pas alors que
[(#MACHIN|={truc})] marchait nickel.

utilisation détournée : il arrive qu’on veuille mettre du html
autour d’une boucle si elle contient des choses, d’où l’utilisation
des blocs <B_..> et </B_..>.

Mais si on veut afficher des trucs que si il y a quelquechose parmi plusieurs boucles ?
Et bien il suffit de l’encadrer d’un bloc IF avec une condition « 1 » :

<B_bloc>
 avant
<BOUCLE_bloc(IF){cond=1}><BOUCLE_a(..)>
 ...
</BOUCLE_a><BOUCLE_b(...)>
 ...
</BOUCLE_b></BOUCLE_bloc>
 apres
</B_bloc>

Si aucune des deux boucles a et b ne sortent de résultats, les
textes avant et apres ne sont pas affichés.
Attention, il faut coller les tags pour ne pas sortir d’espaces
ou de retours la ligne qui empècheraient d’avoir un résultat
vraiment vide.

et après

J’ai dans un coin un début de boucle fichiers qui permet d’itérer
sur des fichiers du disque (ce qui permettrait de faire un explorateur
de fichiers coté serveur) et à l’occas, on pourrait également coder
une variante du foreach sur du xml. on bouclerait alors sur des
paires tag / contenu.
Il faudrait en plus coder un moyen d’écrire
#TAG{attribut}

Si ça vous botte, je vous le laisse comme exercice ;-)

Dernière modification de cette page le 13 juillet 2007

Retour en haut de la page

Vos commentaires

  • Le 14 avril 2008 à 20:21, par Cyril Marion En réponse à : Boucler sur un tableau, un compteur, les langues, une condition ...

    Merci pour ces codes, notamment la boucle_tableau que j’utilise sur un site que je ne peux pas passer en 1.9 !

    Je note cependant un comportement assez étrange : la boucle tableau me retourne un élément dont la clé, au lieu de porter une valeur numérique, porte la valeur ’spip_recursions’... du coup j’ai un enregistrement de trop dans mes résultats, que j’ai beaucoup de mal à filtrer (car je fais une autre boucle derrière...)

    une boucle de ce type :

                    <B_pays_tableau>
                    <h2>Liste des pays cochés</h2>
                    <ul>
                    <BOUCLE_pays_tableau(TABLEAU){var=pays}>
                            <li>Clé : #CLE | Valeur : #VALEUR | Nom : <BOUCLE_nom_pays(MOTS){id_mot=#VALEUR}>#TITRE</BOUCLE_nom_pays></li>
                    </BOUCLE_pays_tableau>
                    </ul>
                    </B_pays_tableau>
                    <h2>Aucun pays n'est sélectionné...</h2>
                    <//B_pays_tableau>

    Me donne le résultat suivant :

    Liste des pays cochés

    • Clé : 0 | Valeur : 137 | Nom : Austria
    • Clé : 1 | Valeur : 7 | Nom : Cyprus
    • Clé : 2 | Valeur : 89 | Nom : Estonia
    • Clé : 3 | Valeur : 10 | Nom : France
    • Clé : spip_recursions | Valeur : 1 | Nom : Titre n’ayant rien à voir

    Comment se débarrasser de cet enregistrement plutôt gênant ?

    Merci !

    • Le 14 avril 2008 à 21:26, par piif En réponse à : spip_recursions

      Ça ressemble à un conflit entre variables de même nom, mais je n’ai jamais constaté ça.
      Par contre, j’ai déjà eu des comportements louches quand il y a des boucles « normales » imbriquées dans des boucles tableau. ça ressemble bien à ton problème.
      Sans être devant ce code exact, avec la même version de spip, c’est pas évident d’en dire plus, désolé

    • Le 17 avril 2008 à 17:00, par Cyril MARION En réponse à : spip_recursions

      J’ai enlevé la 2e boucle imbriquée dans la boucle tableau :

      <B_pays_tableau>
             <h2>Liste des pays cochés</h2>
             <ul>
             <BOUCLE_pays_tableau(TABLEAU){var=pays}>
                 <li>Clé : #CLE | Valeur : #VALEUR</li>
             </BOUCLE_pays_tableau>
             </ul>
             </B_pays_tableau>
             <h2>Aucun pays n'est sélectionné...</h2>
             <//B_pays_tableau>

      Mais j’obtiens toujours cette ligne de résultats en trop :

      Liste des pays cochés

      • Clé : 0 | Valeur : 7
      • Clé : 1 | Valeur : 89
      • Clé : 2 | Valeur : 14
      • Clé : 3 | Valeur : 92
      • Clé : spip_recursions | Valeur : 1

      Quand aux noms de variables, je n’ai aucune idée de là où je peux agir.

    Répondre à ce message

  • Le 28 mars 2008 à 11:34, par ? En réponse à : Boucler sur un tableau, un compteur, les langues, une condition ...

    est ce que la boucle if accepte plusieurs conditions ? Je cherche à n’afficher un bloc dans un boucle article que si une des balises que je veux afficher dans le bloc est présente et sinon ne pas afficher le bloc

    • Le 28 mars 2008 à 13:17, par piif En réponse à : Boucler sur un tableau, un compteur, les langues, une condition ...

      Oui, on peut mettre plusieurs conditions, mais la syntaxe est assez ésotérique, du fait qu’on mixe du spip et du php.
      Voici un exemple :

      <BOUCLE_si(IF){condition (#ENV{machin}|=={#MACHIN}|?{1,0}) && #ENV{truc}|=={#TRUC}|?{1,0})}>...

      on a donc 2 conditions avec un && pour faire un ET entre les 2.
      chacune d’elle effectue un |== pour comparer à quelquechose, mais comme ce filtre ne retourne rien si la condition est fausse, il faut enchainer sur un |? pour avoir 0 ou 1 explicitement.

      La syntaxe #ENV{machin}==#MACHIN && #ENV{truc}==#TRUC nécessite de mettre des apostrophes ou des guillemets, mais dans ce cas, le parseur spip se paume. Je n’ai donc pas trouvé de solution plus simple.

    Répondre à ce message

  • Le 8 août 2006 à 08:49, par piif En réponse à : les exemples

    Je viens de rapatrier le tar.gz et il contient bien les fichiers. Problème de transfert lors de votre download ?

    Sinon, ce code existe désormais sous forme de plugins pour 1.9, ici

    Répondre à ce message

  • Le 7 août 2006 à 22:27, par Didier En réponse à : Les exemples

    Bonjour,

    Je ne trouve rien dans le fichier d’archive, il semble vide. Y a-t-il une autre façon d’obtenir les exemples ?

    Merci d’avances

    Répondre à ce message

Répondre à cet article

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici Les choses à faire avant de poser une question (Prolégomènes aux rapports de bugs. )
Ajouter un document

Retour en haut de la page

Ça discute par ici

  • Import ICS 2 (agenda distant)

    2 août – 35 commentaires

    La version 2 du plugin « import ICS » en reprend la principale fonctionnalité, à savoir l’ajout automatique d’évènements distants dans la liste des évènements d’un site. À la différence de la première version, elle ne dépend pas du plugin « Séminaire » et est (...)

  • Newsletters

    16 janvier 2013 – 374 commentaires

    Ce plugin permet de composer des Info-lettres. Par info-lettre, on désigne ici le contenu éditorial qui va être composé et envoyé par courriel à une liste d’inscrits. Le plugin permet de composer une info-lettre à partir d’un modèle pré-composé, (...)

  • CKeditor 3.0

    4 octobre 2009 – 1217 commentaires

    CKeditor est l’évolution de l’éditeur WYSIWYG : FCKeditor, avec ce plugin vous pourrez utiliser cet éditeur à la place de l’éditeur de spip tout en laissant le choix à vos auteurs de l’éditeur qu’ils préfèrent utiliser. Attention : cet éditeur WYSIWYG (...)

  • GIS 4

    11 août 2012 – 1284 commentaires

    Présentation et nouveautés La version 4 de GIS abandonne la libraire Mapstraction au profit de Leaflet. Cette librairie permet de s’affranchir des librairies propriétaires tout en gardant les mêmes fonctionnalités, elle propose même de nouvelles (...)

  • SPIPr

    23 mars 2015 – 75 commentaires

    SPIPr est à la fois une famille de squelettes et un framework pour le développement front avec SPIP. Prêt à l’emploi, thémable, responsive, et conçu dans une approche d’industrialisation et de développement rapide. Documentation source : (...)

Ça spipe par là