Os loops (DATA) não estão exclusivamente relacionados com consultas SQL [1], mas podem ser executados em todos os tipos de listas de dados.
Por exemplo:
- uma matriz de dados produzida por qualquer função (do quais os iteradores PHP)
- o conteúdo de um ficheiro local em formato XML, CSV, JSON, YAML etc.
- uma lista de ficheiros num diretório do servidor
- uma consulta a um serviço web
- uma consulta SQL (como calculado pelo SPIP, por ex.)
- etc. (LDAP...).
Sintaxe e formatos do loop (DATA)
É um loop capaz de iterar qualquer matriz de dados. A sua sintaxe básica é a seguinte:
<BOUCLE_exemplo(DATA){formato da fonte, dados}>
#BALISES
</BOUCLE_exemplo>
O critério {source format, données}
define os dados em que o loop vai iterar.
A definição de uma fonte de dados requer dois elementos:
— A parte dados
: este elemento pode ser de diversas naturezas:
- uma matriz de dados, por exemplo #ENV*
- o caminho de um ficheiro em disco rígido, ex: fontes/definicoes.csv
- o URL de um ficheiro ou de um serviço web, ex: http://per.sonn.es/bases/phobia.fr.yaml
- ou ainda, qualquer string que o formato seja capaz de transformar em matriz de dados, ex: "select * from flickr.photos.search where text='spip'"
— A parte formato
pode ser tirada da lista abaixo:
- table
(aliás array
ou tableau
), para uma tabela já criada
- csv
, json
, yaml
para um ficheiro composto num destes formatos
- file
para fazer loop nas linhas de um ficheiro
- glob
ou pregfiles
para fazer loop nos ficheiros de um diretório (e mais...)
- rss
(aliás atom
) para ler um fluxo de novidades
- plugins
para listar os plugins ativos no site
- yql
para enviar uma consulta ao serviço web do Yahoo Query Language
- sql
para enviar uma consulta em bruto ao servidor SQL. Atenção, neste caso: 1) a string que especifica a consulta não pode conter quebras de linha; 2) usar a sintaxe {source sql, connecteur:requete}
para enviar a consulta para uma base externa
- ics
para fazer loop em calendários (requer o plugin icalendar: veja Plugin iCalendar)
- etc.
Todos estes formatos já estão disponíveis, e é fácil incluir um novo, criando uma simples função inc_FORMAT_to_array($u)
. Como exemplo, eis a função que transforma um ficheiro JSON numa matriz de dados:
function inc_json_to_array_dist($u) {
if (is_array($json = json_decode($u))
OR is_object($json))
return (array) $json;
}
Pode-se declarar um novo loop DATA num ficheiro inc/minha_fonte_para_array.php
function inc_minha_fonte_para_array_dist($data,$param1='',$param2='') {
// $data contém o conteúdo do ficheiro (local | distant) ou o valor da variável passada no critério.
// $param1, $param2... são os parâmetros facultativos
...
}
e exibí-lo em seguida:
<BOUCLE_exemplo(DATA){source minha_fonte,teste}>
#VALOR
</BOUCLE_exemplo>
Cache:
- O critério {datacache 3600}
permite especificar o período em que o resultado de um loop DATA permanece registrado em cache. Pode-se assim desativar completamente o cache com o critério {datacache 0}
- Ver mais informações sobre os caches dos loops DATA
Filtragem, ordenação, paginação, fusão
Filtros. Como os loops SQL, os loops (DATA)
podem ser filtrados por critérios do tipo {valeur=x}
; os operadores disponíveis são =
, >
, <
, >=
, <=
, ==
(expressão regular) e LIKE
.
No entanto, esta filtragem não é executada a montante da consulta, como no SQL, mas a jusante, na matriz de dados inicialmente recuperada.
Ordenação. As ordenações {par xx}
são igualmente possíveis, com a sua variante {!par xx}
para ordenar em ordem inversa.
Paginação. A paginação funciona normalmente, bem como o critério {offset,limite}
.
Fusão. O critério {fusion /x/y}
também funciona. Por exemplo, para um ficheiro de moradas no formato CSV, se o email é o campo n° 3, poderemos apenas reter um único registo por e-mail com o loop a seguir:
<BOUCLE_csv(DATA){source csv, adresses.csv}{fusion /3}{par /0}{'<br>'}>
#VALEUR{0} : #VALEUR{3}
</BOUCLE_csv>
A fusão ocorre após a ordenação e retém o primeiro elemento encontrado. Deste modo, se uma matriz é ordenada {!par date}
e em seguida fundida pelo e-mail, o registro retido para cada e-mail será o mais recente.
O critério {liste ...}
Para simplificar a escrita de matrizes de dados, quando se trata de uma simples lista de elementos que se pretende indicar manualmente, o loop (DATA)
aceita o critério {liste ...}
, que permite criar uma matriz de dados separados por vírgulas.
Boucle :
<BOUCLE_i(DATA){liste 3,4,5}{"<br>"}>
<BOUCLE_j(DATA){liste 6,7,8}{" "}>
[(#VALEUR|mult{#_i:VALEUR})]
</BOUCLE_j>
</BOUCLE_i>
Resultado:
18 21 24
24 28 32
30 35 40
Nota: usou-se #_i:VALEUR
para referenciar no loop j
o valor processado pelo loop i
.
O critério {enum ...}
<BOUCLE_enumere(DATA){enum 2,10,2}>
#VALEUR
</BOUCLE_enumere>
Resultado:
2 4 6 8 10
<BOUCLE_enum(DATA){enum g,m}{", "}>
#VALEUR
</BOUCLE_enum>
Resultado:
g, h, i, j, k, l, m
val1
e val2
são 2 valores numéricos, ou dois caracteres.O SPIP determina qual dos dois valores é o mais pequeno, este loop irá enumerar os valores entre val1
e val2
. Na primeira forma, o passo não é especificado: il vaut 1 por padrão.
Proteção dos dados manipulados pelos iteradores
O loop (DATA)
protege automaticamente todas as tags que eles contêm, visto que os dados manipulados são, em geral, de origem desconhecida e potencialmente perigosos. Isto também afeta as tags dos formulários (#FORMULAIRE_xx
) que devem, portanto, ser utilizadas com um * como explicado na matéria sobre as tags com asteríscos.
<BOUCLE_foreach_protege(DATA){liste a,b,c,d,e}>
#FORMULAIRE_XXX*{#VALEUR}
</BOUCLE_foreach_protege>
Nota: se você usa o plugin "Bonux", bastará usar um loop (POUR)
, que não tem este comportamento
<BOUCLE_Foreach_non_protege(POUR){liste a,b,c,d,e}>
#FORMULAIRE_XXX{#VALEUR}
</BOUCLE_Foreach_protege>
Leia mais: veja alguns exemplos de loops (DATA)
!