Les itérateurs de SPIP - la boucle (DATA)

SPIP 3.0 a apporté une notion générale de boucle, basée sur les itérateurs de PHP.

  • Apparu en : SPIP 3.0

Les boucles (DATA) ne portent plus exclusivement sur des requêtes SQL [1], mais elles peuvent tourner sur toutes sortes de listes de données.

Par exemple :

  • un tableau de données produit par une fonction quelconque (dont les itérateurs PHP)
  • le contenu d’un fichier local au format XML, CSV, JSON, YAML, etc.
  • une liste de fichiers dans un répertoire du serveur
  • une requête sur un webservice
  • une requête SQL (telle que calculée par SPIP, par ex.)
  • etc. (LDAP...).

Syntaxe et formats de la boucle (DATA)

C’est une boucle capable d’itérer n’importe quel tableau de données. Sa syntaxe de base est la suivante :

<BOUCLE_exemple(DATA){source format, données}>
	#BALISES
</BOUCLE_exemple>

Le critère {source format, données} définit les données sur lesquelles la boucle va itérer.

La définition d’une source de données nécessite deux éléments :

— La partie données : cet élément peut être de plusieurs natures :
-  un tableau de données, par exemple #ENV*
-  le chemin d’un fichier sur le disque dur, ex : sources/definitions.csv
-  l’URL d’un fichier ou d’un webservice, ex : http://per.sonn.es/bases/phobia.fr.yaml
-  ou encore, une chaîne quelconque que le format saura transformer en tableau de données, ex : "select * from flickr.photos.search where text='spip'"

— La partie format est à prendre dans la liste ci-dessous :
-  table (alias array ou tableau), pour un tableau déjà créé
-  csv, json, yaml pour un fichier composé dans l’un de ces formats
-  file pour boucler sur les lignes d’un fichier
-  glob ou pregfiles pour boucler sur les fichiers d’un répertoire (et plus...)
-  rss (alias atom) pour lire un flux de nouvelles
-  plugins pour lister les plugins actifs sur le site
-  yql pour envoyer une requête sur le webservice de Yahoo Query Language
-  sql pour envoyer une requête brute au serveur SQL . Attention dans ce cas : 1) la chaîne spécifiant la requête ne doit pas contenir de fins de lignes 2) utiliser la syntaxe {source sql, connecteur:requete} pour envoyer la requête sur une base externe
-  ics pour boucler sur des calendriers (nécessite le plugin icalendar : lire Plugin iCalendar)
-  etc.

Tous ces formats sont déjà disponibles, et il est très aisé d’en ajouter un nouveau, en créant une simple fonction inc_FORMAT_to_array($u). A titre d’exemple voici la fonction qui transforme un fichier JSON en tableau de données :

function inc_json_to_array_dist($u) {
  if (is_array($json = json_decode($u))
  OR is_object($json))
    return (array) $json;
}

On peut déclarer une nouvelle boucle DATA dans un fichier inc/ma_source_to_array.php

function inc_ma_source_to_array_dist($data,$param1='',$param2='') {
     // $data contient le contenu du fichier (local | distant) ou bien la valeur de la variable passée dans le critère.
    // $param1, $param2... sont des paramètres facultatifs
...
}

et l’afficher ensuite :

<BOUCLE_exemple(DATA){source ma_source,test}>
	#VALEUR
</BOUCLE_exemple>

Cache :
-  Le critère {datacache 3600} permet de spécifier la durée pendant laquelle le résultat d’une boucle DATA est enregistré en cache. On peut donc désactiver tout cache avec le critère {datacache 0}
-  Voir plus d’infos sur les caches des boucles DATA

Filtrage, tri, pagination, fusion

Filtres. Comme les boucles SQL, les boucles (DATA) peuvent être filtrées par des critères du type {valeur=x} ; les opérateurs disponibles sont =, >, <, >=, <=, == (expression rationnelle) et LIKE.

Cependant ce filtrage s’effectue non pas en amont lors de la requête, comme en SQL, mais en aval, sur le tableau de données initialement récupéré.

Tris. Les tris {par xx} sont également possibles, avec leur variante {!par xx} pour trier en ordre inverse.

Pagination. La pagination fonctionne normalement, ainsi que le critère {offset,limite}.

Fusion. Le critère {fusion /x/y} fonctionne aussi. Par exemple, pour un fichier d’adresses au format CSV, si l’email est le champ n° 3, on pourra ne retenir qu’un seul enregistrement par email avec la boucle suivante :

 <BOUCLE_csv(DATA){source csv, adresses.csv}{fusion /3}{par /0}{'<br>'}> 
 	#VALEUR{0} : #VALEUR{3} 
 </BOUCLE_csv> 

La fusion se fait après le tri, et retient le premier élément rencontré. De cette manière, si un tableau est trie {!par date} puis fusionné sur l’email, l’enregistrement retenu pour chaque email sera le plus récent.

Le critère {liste ...}

Pour simplifier l’écriture de tableaux de données, lorsqu’il s’agit d’une simple liste d’éléments qu’on veut indiquer manuellement, la boucle (DATA) accepte le critère {liste ...}, qui permet de constituer un tableau de données en séparant celles-ci par des virgules.

Boucle :

<BOUCLE_i(DATA){liste 3,4,5}{"<br>"}>
	<BOUCLE_j(DATA){liste 6,7,8}{" "}>
		[(#VALEUR|mult{#_i:VALEUR})]
	</BOUCLE_j>
</BOUCLE_i>

Résultat :

18 21 24
24 28 32
30 35 40

A noter : on a utilisé #_i:VALEUR pour référencer dans la boucle j la valeur calculée par la boucle i.

Voir aussi Deux itérateurs simples : les listes et les énumérations

Le critère {enum ...}

<BOUCLE_enumere(DATA){enum 2,10,2}>
      #VALEUR
</BOUCLE_enumere>

Résultat :

2 4 6 8 10

<BOUCLE_enum(DATA){enum g,m}{", "}>
	#VALEUR
</BOUCLE_enum>

Résultat :

g, h, i, j, k, l, m

val1 et val2 sont 2 valeurs numériques, ou bien 2 caractères. SPIP déterminant laquelle des 2 valeurs est la plus petite, cette boucle va énumérer les valeurs entre val1 et val2. Dans la première forme, le pas n’est pas précisé : il vaut 1 par défaut.

Voir aussi Deux itérateurs simples : les listes et les énumérations

Protection des données manipulées par les itérateurs

La boucle (DATA) protège automatiquement toutes les balises qui sont à l’intérieur, car les données qu’on y manipule sont en général de provenance inconnue et potentiellement dangereuse. Cela impacte aussi les balises des formulaires (#FORMULAIRE_xx) qu’il faut donc utiliser avec un * comme expliqué dans l’article sur les balises étoilées.

<BOUCLE_foreach_protege(DATA){liste a,b,c,d,e}>
	#FORMULAIRE_XXX*{#VALEUR}
</BOUCLE_foreach_protege>

A noter : si vous utilisez le plugin "Bonux", il suffira d’utiliser une boucle (POUR), qui elle n’a pas ce comportement.

<BOUCLE_Foreach_non_protege(POUR){liste a,b,c,d,e}>
	#FORMULAIRE_XXX{#VALEUR}
</BOUCLE_Foreach_protege>

 

Lire la suite : régalez-vous avec des exemples de boucles (DATA) !

Notes

[1Sans surprise, l’itérateur classique de SPIP s’appelle SQL : il exécute la requête telle que SPIP l’a calculée, et sait parcourir la liste de résultats pour les envoyer à la boucle.

Auteur Fil, Matthieu Marcillaud Publié le : Mis à jour : 21/02/24

Traductions : عربي, English, français, Nederlands