#ARRAY

The #ARRAY tag may contain a PHP table or array, i.e. a collection of key/value pairs that needs to be stored so that they can be reused later in the template.

The array must be declared using the #SET tag and can then later be retrieved using the #GET tag [1].

It can be then be used, amongst other applications, when associated with the IN criterion in a loop.

Declaring a table array and retrieving the values

-  #SET{my_table, #ARRAY{key1,value1,key2,value2}}
creates the my_table variable and assigns to it a PHP array as a value, which can be illustrated as shown below:

KeysValues
key1 value1
key2 value2

It is not necessary to surround the character strings with simple or double quotes, except when specifying an empty character string, which is written as ’’.

-  For testing purposes, you can display an array’s contents using the |foreach filter.

[(#GET{my_table}|foreach)] will display:

  • key1=> value1
  • key2=> value2

-  The value associated with a given key can be retrieved using the |table_valeur filter:

[(#GET{my_table}|table_valeur{key1})] returns value1.

-  Checking the presence of a value in an array with the |find filter [2]:

[(#GET{my_table}|find{valeur2}|oui)
  This sentence displays if the value is in the array.
]

Fill up an array dynamically

One useful aspect of arrays is being able to populate them dynamically with the results of one or more SPIP loops.

The array should then be declared with a #SET before the loop: #SET{my_table,#ARRAY}

Within the loop, a new #SET redefines my_table for each iteration of the loop: we retrieve its value with a #GET and add one a new value using the |push or |array_merge filters.

#SET{my_table,#ARRAY}
<BOUCLE(...)>
    #SET{my_table,
        #GET{my_table}|push{#COMPTEUR_BOUCLE}
    }
</BOUCLE>

The order of the values stored in the array depends upon the sorting criteria employed by the loop.

-  |push simply adds a value to the end of the array. The key is automatically indexed: it increments by 1 for each iteration of the loop starting at 0 (so the first key value is 0, followed by 1, 2, 3,...).

Example: create an array called selected_words containing the #ID_MOT values of all the keywords linked to a given article.

#SET{selected_words, #ARRAY}
<BOUCLE_themes(MOTS){id_article}>
  #SET{selected_words, #GET{selected_words}|push{#ID_MOT}}
</BOUCLE_themes>

If the keywords linked to this article have the ID numbers 4, 9 and 18, then [(#GET{selected_words}|foreach)] will return:

  • 0=>4
  • 1=>9
  • 2=>18

Note that [(#GET{selected_words}|table_valeur{2})] will return 18, the value associated with the key value 2, that being the third value in the array in sequential order.

-  |array_merge adds a key/value pair to the end of the array. This method therefore makes it possible to force the "names" of the keys.

Attention (1): if a key appears several times, only the last value for that key will be retained.

Attention (2): the key that you want to force can not be of a numeric type. In fact, the documentation about array_merge states:

If you want to a pass a single array to this function and it has numeric indices, the keys will be reindexed normally.

There are two solutions to this restriction:

-  prefix that key with an alphabetic value:

#SET{selected_words, #ARRAY}
<BOUCLE_themes(MOTS) {id_article}>
  [(#SET{selected_words,
      #GET{selected_words}|array_merge{#ARRAY{
          keyword#ID_MOT, #TITRE
      }}
  })]
</BOUCLE_themes>

[(#GET{selected_words}|foreach)] returns:

  • keyword4=>Apply
  • keyword9=>Banana
  • keyword18=>Carrot

-  invert the key and value, on the condition that the value is not itself also numeric:

#SET{selected_words, #ARRAY}
<BOUCLE_themes(MOTS) {id_article}>
  [(#SET{selected_words,
      #GET{selected_words}|array_merge{#ARRAY{
          #TITRE, #ID_MOT
      }}
  })]
</BOUCLE_themes>

[(#GET{selected_words}|foreach)] returns:

  • Apple=>4
  • Banana=>9
  • Carrot=>18

In this case, we can apply the PHP function |array_flip as a filter on the final table (after the loop): [(#SET{selected_words, #GET{selected_words}|array_flip})]

[(#GET{selected_words}|foreach)] then returns:

  • 4=>Apple
  • 9=>Banana
  • 18=>Carrot

Using the array in a loop with the IN operator

Taking our example of the selected_words array containing the #ID_MOT numbers, we can then select the articles linked to the same keywords as our original article using the criterion IN value1, value2[, value3,..., valueN] criteria.

#SET{selected_words, #ARRAY}
<BOUCLE_themes(MOTS){id_article}>
  #SET{selected_words, #GET{selected_words}|push{#ID_MOT}}
</BOUCLE_themes>

<BOUCLE_memes_themes(ARTICLES) {id_mot IN #GET{selected_words}}>
  #TITRE <br />
</BOUCLE_memes_themes>

This type of usage has many applications, specifically whenever we want to select objects using several criteria that can not be part of the same single loop, and then mixing them up in a different order with a single sort criteria.

Examples of using arrays

-  Condition display depending on the page’s (value of (#ENV):

[(#ENV{page}|in_array{#ARRAY{0,article,1,rubrique,2,site}}|oui)
Conditional display: the page is either for an article, a section or a site. ]

-  Conditional display depending on a variable passed in the URL [3] :

<BOUCLE_all_words(MOTS){par titre}{", "}>
  <a href="[(#SELF|parametre_url{lolo,#ID_MOT})]">#TITRE</a>
</BOUCLE_all_words>

#SET{the_words, #ARRAY}
<BOUCLE_specific_words(MOTS){id_article}>
  #SET{the_words, #GET{the_words}|push{#ID_MOT}}
</BOUCLE_specific_words>

[<br />This will display if the value of the 'lolo' variable passed in the URL exists in a table called 'the_words' that has been declared and populated beforehand.
  (#ENV{lolo}|in_any{#GET{the_words}}|oui)]

-  Select the articles of a section and additionally those associated with a keyword, then list all of these articles sorted by date.

#SET{the_articles,#ARRAY}
<BOUCLE_articles_in_section(ARTICLES){id_rubrique}>
  #SET{the_articles,#GET{the_articles}|push{#ID_ARTICLE}}
</BOUCLE_articles_in_section>
<BOUCLE_articles_with_keyword(ARTICLES){id_mot}>
  #SET{les_articles,#GET{the_articles}|push{#ID_ARTICLE}}
</BOUCLE_articles_with_keyword>

<BOUCLE_final_display(ARTICLES){id_article IN #GET{the_articles}}{par date}>
  <br />#TITRE
</BOUCLE_final_display>

Footnotes

[1Refer to #SET and #GET for more details.

[2|find corresponds to the PHP function in_array, with the only difference being that this filter does not generate the error message "Warning : in_array() [function.in-array] : Wrong datatype for second argument." if the variable passed turns out not to be an array. When a variable is generated dynamically, we can never really be sure if it actually does exist at all or even if it is actually an array.

Author Mark Published : Updated : 14/07/23

Translations : عربي, català, English, Español, français, Nederlands