La syntaxe des boucles

Syntaxe de base

La syntaxe simplifiée d’une boucle est la suivante :

<BOUCLEn(TYPE){critère1}{critère2}{...}{critèrex}>
* Code HTML + balises SPIP
<BOUCLEn>

On a vu, dans l’explication sur les boucles et les balises, que le « Code HTML + balises SPIP » se répétait autant de fois que la boucle obtenait d’éléments tirés de la base de données (c’est-à-dire une fois, plusieurs fois, ou zéro fois).

La ligne importante, ici, est :

<BOUCLEn(TYPE){critère1}{critère2}{...}{critèrex}>

-  L’élément BOUCLE est l’ordre indiquant qu’il s’agit d’une boucle SPIP ; on ne peut donc pas le modifier ; dit autrement, toutes les boucles de SPIP commencent par l’instruction BOUCLE.

-  L’élément n est le nom ou le numéro de la boucle, librement choisi par le webmestre pour chaque boucle qu’il utilise (attention : on prendra soin de nommer ses boucles avec uniquement des caractères alphanumériques non accentués et le tiret-bas « underscore » ; c’est-à-dire des caractères de la classe [a-zA-Z0-9_]. On verra plus loin qu’il est possible (c’est même tout l’intérêt de la manœuvre) d’utiliser plusieurs boucles dans un même squelette : les nommer est donc indispensable pour les identifier.

Si vous décidez de numéroter vos boucles, la syntaxe devient par exemple (pour la boucle 5) :
<BOUCLE5...> ... </BOUCLE5>

Si vous décidez de donner un nom à vos boucles (c’est généralement plus pratique, votre code est plus lisible), il faut impérativement faire précéder ce nom par le symbole « _ » (que l’on appelle habituellement underscore). Par exemple :
<BOUCLE_sousrubriques...> ... </BOUCLE_sousrubriques>

-  L’élément (TYPE) est primordial : il indique quel type d’éléments on veut récupérer. La syntaxe est importante : le TYPE est indiqué entre parenthèses (sans espaces), en majuscules, et ce TYPE doit correspondre obligatoirement à l’un des types prévus dans SPIP (qu’on trouvera dans la présente documentation) : ARTICLES, RUBRIQUES, AUTEURS, BREVES, etc.

Pour l’exemple précédent, on aurait donc :

<BOUCLE_sousrubriques(RUBRIQUES){...}>
...
</BOUCLE_sousrubriques>

-  Les critères {critère1}{critère2}...{critèrex} indiquent à la fois selon quels critères on veut sélectionner les éléments de la base de données (afficher les sous-rubriques incluses dans cette rubrique, afficher les autres rubriques installées au même niveau hiérarchique que la présente rubrique...), et la façon dont on va classer ou sélectionner les éléments (classer les articles selon leur date, selon leur titre... afficher uniquement les 3 premiers articles, afficher la moitié des articles...). Comme on peut combiner les critères, on peut très aisément fabriquer des requêtes très puissantes, du genre « afficher la liste des 5 articles les plus récents écrits par cet auteur ».

Les critères sont entre accolades ; ils peuvent être séparés les uns des autres par un espace. Exemple :

<BOUCLE_meme_auteur(ARTICLES){id_auteur}{par date}{inverse}{0,5}>
...
</BOUCLE_meme_auteur>

Les différents critères et leur syntaxe seront explicités par la suite, pour chaque type de boucle (certains critères fonctionnent pour tous les types de boucles, d’autres sont spécifiques à certaines boucles).

Syntaxe complète

La syntaxe indiquée précédemment peut être complétée par des éléments conditionnels ou [depuis SPIP 4.0] par des éléments inconditionnels mais associés aux retours de la boucle.

Éléments conditionnels  : la boucle précédemment introduite affiche successivement les éléments contenus à l’intérieur de la boucle. SPIP permet de plus d’indiquer ce qu’on affiche avant et après la boucle au cas où elle contient un ou plusieurs résultats, et ce qu’on affiche s’il n’y a aucun élément.

Cela donne :

<BBn>
* Code optionnel non conditionnel avant
<Bn>
* Code optionnel avant
<BOUCLEn(TYPE){critère1}{critère2}{...}{critèrex}>
* Code + balises SPIP
</BOUCLEn>
* Code optionnel après
</Bn>
* Code alternatif
<//Bn>
* Code optionnel non conditionnel après
<//BBn>

Le code optionnel « avant » (précédé de <Bn>) n’est affiché que si la boucle contient au moins une réponse. Il est affiché avant les résultats de la boucle.

Attention :
Bien qu’il s’affiche avant le corps principal de la boucle, le code optionnel « avant » est calculé après l’exécution de la boucle (ce qui permet, par exemple, d’afficher la balise #TOTAL_BOUCLE avant l’affichage des retours particuliers de la boucle).

Le code optionnel « après » (terminé par </Bn>) n’est affiché que si la boucle contient au moins une réponse. Il est affiché après les résultats de la boucle.

Le code alternatif (terminé par <//Bn>) est affiché à la place de la boucle (et donc également à la place des codes optionnels avant et après) si la boucle n’affiche rien soit parce que la base de données n’a fourni aucune réponse, soit parce que le code utilisant ces réponses dans la boucle n’affiche rien.

Par exemple, le code :

<B1>
  Cette rubrique contient les éléments suivants:
  <ul>
    <BOUCLE1(ARTICLES){id_rubrique}>
    <li>#TITRE</li>
    </BOUCLE1>
  </ul>
</B1>
  Cette rubrique ne contient pas d'article.
<//B1>

donne les résultats suivants :

-  s’il y a un seul article :

Cette rubrique contient les éléments suivants:
 <ul>
   <li>Titre de l'article</li>
</ul>

-  s’il y a plusieurs articles :

 Cette rubrique contient les éléments suivants:
 <ul>
   <li>Titre de l'article 1</li>
   <li>Titre de l'article 2</li>
   ...
   <li>Titre du dernier article</li>
</ul>

-  s’il n’y a aucun article :

Cette rubrique ne contient pas d'article.

Éléments inconditionnels mais associés à la boucle

SPIP 4.0 introduit la possibilité de spécifier des parties inconditionnelles avant et après chaque boucle, à l’intérieur desquelles on peut interroger les balises relatives à l’exécution la boucle, qu’il y ait ou non un résultat.

Il faut pour cela utiliser <BB> et </BB>, comme dans l’exemple suivant :

<BB_maboucle> 
<div class="style_maboucle">
    <h1>Il y a [(#TOTAL_BOUCLE) ]articles</h1>
    <B_maboucle>
      <ul>
      <BOUCLE_maboucle(ARTICLES){id_article?}{0,5}>
          <li>#ID_ARTICLE::#TITRE</li>
      </BOUCLE_maboucle>
      </ul>
    </B>
    <p>Vous avez peut-être fait une erreur?...</p>
   <//B>
</div>
</BB>

On pourra notamment y utiliser les balises #PAGINATION, #TRI, #TOTAL_BOUCLE et #GRAND_TOTAL, pour par exemple construire les entêtes d’un tableau ou d’une liste de résultats.

Tables conditionnelles

À partir de SPIP 4.0, il est possible d’écrire une boucle sur une table qui peut exister, ou ne pas exister. C’est utile pour, par exemple, créer une partie qui ne s’affiche que si
le plugin qui crée cette table a été installé et activé. Pour éviter une erreur si la table n’existe pas, on ajoute un ? après son nom.

Par exemple, le plugin organiseur (qui faisait partir des plug-in-dist) génère un flux RSS qui fournit des informations relatives aux forums perso... seulement si la table FORUMS existe :

<BOUCLE_RSS2(FORUMS ?){!par date_heure}{!doublons F}{tout}{statut=perso} >

Syntaxe raccourcie

Il est possible dans certains cas d’utiliser une écriture allégée des boucles.

Ainsi pour ne récupérer que le nombre total des retours de la requête (avec la balise #TOTAL_BOUCLE) on pourra écrire :

<BOUCLE_a(ARTICLES) />#TOTAL_BOUCLE<//B_a>

en lieu et place de :

<BOUCLE_a(ARTICLES) > </BOUCLE_a>#TOTAL_BOUCLE</B_a>

Cette écriture allégée peut aussi être utile lorsqu’on ne cherche qu’à remplir un tableau de « doublons » :

<BOUCLE_a(ARTICLES) {critères ...} {doublons}/>

Boucles anonymes

Depuis SPIP 4.0, il est également possible de créer une boucles anonyme, c’est à dire sans nom, lorsque que cette boucle n’est pas imbriquée. Un grand nombre de boucles simples, complètes ou partielles, sont concernées.

La syntaxe est la même sauf qu’il n’y a pas le numéro ou le nom n de la boucle.

Exemple :

<BB>
  <div style="border:5px solid red;padding:20px;">
    <h1>[(#TOTAL_BOUCLE) ]articles</h1>
    <B>
      <ul>
      <BOUCLE(ARTICLES){id_article?}{0,5}>
        <li>#ID_ARTICLE::#TITRE</li>
      </BOUCLE>
      </ul>
    </B>
      <p>Vous avez peut-être fait une erreur?...</p>
    <//B>
  </div>
</BB>

On peut evidemment avoir plusieurs boucles anonymes dans une page, et une même boucle anonyme peut être présente plusieurs fois dans la page.

En interne, et pour référencer cette boucle dans la page de debug (obtenue avec var_mode=debug) le compilateur génère un identifiant unique pour chaque boucle anonyme (n° de ligne du fichier source + hash).

Des critères d’environnement en cascade

Chaque boucle effectue la sélection des éléments tirés de la base de données en fonction de critères. Certains de ces critères correspondent à l’environnement dans lequel se trouve la boucle.

Par exemple : si on prévoit une boucle du genre « Afficher les articles inclus dans cette rubrique », il faut savoir de quelle rubrique il s’agit. C’est ce que l’on nomme l’environnement.

-  L’environnement fourni par l’URL

Lorsque l’on visite une page d’un site SPIP, son adresse contient généralement une variable. Par exemple : spip.php?rubrique15

Cette variable définit donc un premier environnement : la boucle « Afficher les articles inclus dans cette rubrique » doit alors être comprise comme « Afficher les articles de la rubrique 15 ».

Clairement, avec le même code de squelette, si on appelle l’adresse : spip.php?rubrique7 ; l’interprétation de cette boucle deviendra « Afficher les articles de la rubrique 7 ».

-  L’environnement fourni par les autres boucles

À l’intérieur d’une boucle, l’environnement est modifié par chaque élément de la boucle. En plaçant des boucles les unes à l’intérieur des autres, on hérite ainsi d’environnements imbriqués les uns dans les autres.

Ainsi, dans la structure suivante :

<BOUCLE_articles: afficher les articles de cette rubrique>
  Afficher le titre de l'article
  <BOUCLE_auteurs: afficher les auteurs de cet article>
    Nom de l'auteur
  </BOUCLE_auteurs>
</BOUCLE_articles>

On doit comprendre que :
-  la première boucle (BOUCLE_articles) affiche les articles en fonction de la rubrique, selon l’environnement fournit par l’URL (id_rubrique=15 par exemple) ;
-  dans cette boucle, on obtient un ou plusieurs articles ;
-  « à l’intérieur » de chacun de ces articles, on a un environnement différent (celui de l’article, c’est-à-dire, par exemple, id_article=199) ;
-  la seconde boucle (BOUCLE_auteurs), qui est installée à l’intérieur de la première boucle, dépend pour chacune de ses exécutions successives (elle est exécutée pour chaque article de la première boucle) : « afficher les auteurs de cet article » devient successivement « afficher les auteurs du premier article », « du deuxième article » et ainsi de suite.

On voit que, par l’imbrication de boucles successives, on obtient différentes boucles, incluses les unes dans les autres, qui dépendent du résultat des boucles dans lesquelles elles sont situées. Et finalement, la toute première boucle (celle qui contient toutes les autres) dépend d’un paramètre fixé dans l’adresse de la page.

Boucles incluses et boucles successives

Si l’on peut inclure des boucles les unes à l’intérieur des autres (chaque boucle incluse dépendant alors du résultat de la boucle à l’intérieur de laquelle elle est installée), on peut tout aussi bien installer des boucles les unes à la suite des autres ; des boucles successives n’influent pas les unes sur les autres.

Par exemple, la page d’une rubrique est typiquement constituée des éléments suivants :

<BOUCLE_rubrique(RUBRIQUES){id_rubrique}>
  <ul>Titre de la rubrique
  <BOUCLE_articles(ARTICLES){id_rubrique}>
    <li> Titre de l'article</li>
  </BOUCLE_articles>
  <BOUCLE_sous_rubriques(RUBRIQUES){id_rubrique}>
    <li> Titre de la sous-rubrique </li>
  </BOUCLE_sous_rubriques>
  </ul>
</BOUCLE_rubrique>
  <ul>Il n'y a pas de rubrique à cette adresse.</ul>
<//B_rubrique>

La première boucle (BOUCLE_rubrique) dépend de la variable passée dans l’URL de la page (id_rubrique=15 par exemple).

Les boucles suivantes (BOUCLE_articles et BOUCLE_sous_rubriques) sont installées à l’intérieur de la première boucle. Ainsi, s’il n’existe pas de rubrique 15, la première boucle ne donne aucun résultat (le code alternatif « Il n’y a pas de rubrique... » est affiché), et donc les deux boucles incluses sont totalement ignorées. Mais s’il existe une rubrique 15, ces deux sous-boucles seront analysées.

On constate également que ces deux boucles se présentent l’une après l’autre. Ainsi, elles fonctionnent en fonction de la première boucle, mais indépendamment l’une de l’autre. S’il n’y a pas d’articles dans la rubrique 15 (BOUCLE_articles), on affichera tout de même la liste des sous-rubriques de la rubrique 15 (BOUCLE_sous_rubriques) ; et inversement.

Compteurs

Deux balises permettent de compter les résultats dans les boucles.


-  #TOTAL_BOUCLE retourne le nombre total de résultats affichés par la boucle. On peut l’utiliser dans la boucle, dans ses parties optionnelles — « avant » et « après » — ou même dans la partie alternative « après » la boucle.
Par exemple, pour afficher le nombre de documents associés à un article :

<BOUCLE_art(ARTICLES){id_article}>
  <BOUCLE_doc(DOCUMENTS) {id_article}></BOUCLE_doc>
    [il y a (#TOTAL_BOUCLE) document(s).]
  <//B_doc>
</BOUCLE_art>

Attention : si la partie centrale de la boucle ne retourne rien (c’est le cas avec la boucle <BOUCLE_doc> ci-dessus, qui ne sert qu’à compter le nombre de résultats), le #TOTAL_BOUCLE ne pourra être affiché que dans la partie alternative « après » de la boucle (<//B_doc>).


-  #COMPTEUR_BOUCLE retourne le numéro de l’itération actuelle de la boucle. On peut par exemple l’utiliser pour numéroter des résultats :

<BOUCLE_art(ARTICLES) {par date} {inverse} {0,10}>
#COMPTEUR_BOUCLE - #TITRE<br>
</BOUCLE_art>

Auteur L’équipe de SPIP Publié le : Mis à jour : 05/05/23

Traductions : عربي, català, Deutsch, English, Español, français, italiano, Nederlands, русский, українська