O critério {doublons}
, uma vez conhecido, torna-se rapidamente indispensável nos seus templates [1]. Apesar do seu uso um tanto peculiar, permite ordenações bem interessantes, embora não muito óbvias na documentação básica em Spip.net, que nos diz:
O critério {doublons}
ou {unique}
[2]:
impede a exibição de resultados já exibidos em outros loops com este mesmo critério. Estes dois critérios são rigorosamente idênticos.
Idênticos? Nem tanto! Ao longo das versões do SPIP, o doublons foi sendo enriquecido com funcionalidades adicionais:
- pode-se nomear os doublons, possibilitando a coexistência de vários deles num mesmo código,
- também permite algumas acrobacias spipianas com o anti-doublons!
Uso básico: não encontrar elementos já tratados na página
Um exemplo é dado no template «sommaire» da dist [3]
<BOUCLE_materias_recentes(ARTICLES) {par date}{inverse} {0,2} {doublons}>
elementos a exibir, por exemplo #TITRE
</BOUCLE_materias_recentes>
<BOUCLE_outras_materias(ARTICLES) {par date}{inverse} {doublons}>
elementos a exibir, por exemplo #TITRE
</BOUCLE_outras_materias>
Trata-se de listar as matérias do site por ordem cronológica inversa E de reservar às duas matérias mais recentes um tratamento particular. Como pode ver, os loops "_materias_recentes" e "_outras_materias" são construídas da mesma maneira. Em tese, deveriam retornar a mesma lista de matérias.
Graças ao critério "doublons" , as duas matérias mais recentes, já tratadas no primeiro loop, não serão incluídas na lista exibida pelo loop "_outras_materias" .
Outro uso comum: excluir elementos
Nosso grande clássico: excluir de acordo com uma palavra-chave
Vê-se regularmente na lista spip-users este tipo de problema:
"Não consigo excluir elementos em função da sua palavra-chave.
Eu tento:
<BOUCLE_secoes(RUBRIQUES) {racine} {titre_mot!=invisivel}{par num titre, titre}>
mas não funciona"
E com razão!
O utilizador quer aqui selecionar todas as seções que não tenham sido vinculadas à palavra-chave "invisivel". No entanto, o que a base de dados percebe com {titre_mot != invisivel}
, é que ela deve selecionar todas as seções que TÊM uma palavra-chave E que a palavra-chave seja diferente de "invisivel".
E isso muda tudo. Visto que no resultado constará, por exemplo, uma seção à qual foi vinculada uma palavra-chave "coisa", portanto diverente de "invisivel" (ok!), inclusive se a seção estiver vinculada à palavra-chave "invisivel" (arg!) e não irá constar uma seção que não tenha nenhuma palavra-chave (o inverso do resultado desejado!). [4]
A solução: encadear um loop vazio que seleciona de acordo com a palavra-chave e outro loop que retorna os resultados usando o critério {doublons}
.
Retomando o nosso exemplo acima, seria:
<BOUCLE_excluir(RUBRIQUES) {racine} {titre_mot=invisivel}{doublons}>
</BOUCLE_excluir>
Este loop seleciona todas as seções vinculadas à palavra-chave "invisivel" , mas não exibe nada.
<BOUCLE_secoes(RUBRIQUES) {racine}{par num titre, titre} {doublons}>
{o tratamento a realizar aqui}
</BOUCLE_secoes>
Este segundo loop selecionará, graças ao critério doublons, todas as outras seções e lhes aplicará o tratamento requerido.
Nomear os doublons para usar vários no mesmo ficheiro
Objetivo: gerir numa página de entrada a exibição de links para matéras e comunicados. A apresentação das duas matérias mais recentes publicadas e dos dois comunicados mais recentes é diferente das outras.
Por exemplo, encontra-se aqui o mesmo esquema já visto com os loops da DIST. Trata-se de fazer coexistir sem conflito loops muito próximos. Nomear os doublons evitará que a ordenação de uma interfira na ordenação da outra.
<BOUCLE_comunicados_recentes(ARTICLES) {!par date}{id_mot=1} {0,2} {doublons com}>
elementos a exibir, por exemplo #TITRE
</BOUCLE_comunicados_recentes>
<BOUCLE_outros_comunicados(ARTICLES) {!par date}{id_mot=1} {doublons com} >
elementos a exibir, por exemplo #TITRE
</BOUCLE_outros_comunicados>
<BOUCLE_materias_recentes(ARTICLES) {!par date} {0,2} {doublons mat}>
elementos a exibir, por exemplo #TITRE
</BOUCLE_materias_recentes>
<BOUCLE_outras_materias(ARTICLES) {!par date} {doublons mat} >
elementos a exibir, por exemplo #TITRE
</BOUCLE_outras_materias>
De modo geral, nomear os seus doublons é uma boa prática para evitar qualquer conflito atual, mas também futuro (os templates evoluem). Contribui também para a legibilidade do seu código.
No âmbito de uma utilização avançada, você pode experimentar o uso de tags SPIP. Por exemplo: {doublons #TITRE}
ou mesmo {doublons #_meuloop:TITRE}
ou até {doublons (#_meuloop:TITRE|supprimer_numero)
.
Utilização avançada: anti-doublons ou como constituir uma pilha de dados a processar
Mecânica do anti-doublons
Aqui, "doublons" vai permitir reunir o resultado de vários loops usando diferentes critérios, e "!doublons" vai permitir aplicar os tratamentos desejados a essa pilha de itens.
O esquema de uso é este:
Seleciona-se uma primeira série de matérias (sem exibir nada)...
<BOUCLE0(ARTICLES){id_mot=2}{doublons A}></BOUCLE0>
... em seguida uma segunda série de matérias (também sem exibir nada)....
<BOUCLE1(ARTICLES){id_auteur=1}{doublons A}></BOUCLE1>
... ordena-se segundo a necessidade e exibe-se tudo, graças ao anti-doublons.
<BOUCLE2(ARTICLES){par date}{!doublons A}>#TITRE<br></BOUCLE2>
Um exemplo de anti-doublons
Objetivo: fazer um loop que recupere as matérias de todas as seções, excepto das seções 2 e 3, E, para os da seção 4, apenas os que tenham menos de 60 dias.
A solução: montamos um primeiro loop que buscará todas as matérias, excluindo as das seções 2 e 3, mas também as da 4...
<BOUCLE0(ARTICLES) {id_rubrique !IN 2,3,4}{doublons tri1}></BOUCLE0>
.... em seguida, é preciso dedicar a esta seção um segundo loop...
<BOUCLE1(ARTICLES) {id_rubrique=4}{age<60}{doublons tri1}></BOUCLE1>
...e é num último loop que se faz a exibição, graças ao anti-doublons, das matérias selecionadas, ordenadas de acordo com a sua escolha.
<BOUCLE2(ARTICLES){par date}{!doublons tri1}>#TITRE<br></BOUCLE2>