Top Code 2024, les challenges sont de nouveau disponibles dans les boards pour les participant(e)s => Boards

Les tableaux en PHP : ordonnez vos données grâce aux tableaux PHP

Présentation des tableaux en PHP et techniques plus avancées pour les remplir, les tester, les fusionner.

Si tu n’est pas encore familier des tableaux, ou array, en PHP, tu découvriras les bases de l’utilisation de cet outil indispensable. Si tu connais déjà tes fondamentaux, regarde du côté de l’initialisation ou de la fusion des tableaux, il y a sans doute des trucs et astuces à découvrir. La section « Aller + loin » peut te donner plus d’informations aussi 😉

Sommaire :

On démarre…

Les tableaux PHP, à quoi ça sert ?

Quand on débute la programmation, peu importe le langage, on apprend que dans une variable, on peut stocker une seule information : un nombre, une chaîne de caractères, un booléen (vrai ou faux), etc. Mais on a souvent besoin de manipuler un ensemble d’informations. Et un tableau peut justement stocker plusieurs informations au même endroit. Principalement pour deux raisons :

  • J’utilise un tableau pour stocker plusieurs fois une information semblable. Par exemple un tableau de nombres entiers, un tableau de mots (= chaîne de caractères).
  • J’utilise un tableau pour stocker une information de façon détaillée et précise. Une personne peut être définie par son prénom, son nom, son âge, sa profession, etc. On utilisera ici la notion de « clé / valeur » pour repérer les différentes valeurs selon une clé nommée. On parle alors de tableau associatif.
// Exemple 1
$nombres = [1, 2, 3, 4, 5]; // Nombres entiers
$mots = ['Il', 'était', 'une', 'fois']; // Chaines de caractères

// Exemple 2
$personne = [
    'prenom' => 'John',
    'nom' => 'Doe',
    'age' => 30,
    'profession' => 'PHP Expert'
];

Bonne pratique : un tableau associatif peut contenir des éléments de différents types, mais pas un tableau « plat ». On évitera donc des tableaux de ce genre :

$personne = ['John', 'Doe', 30, 'PHP Expert']; // Mélange chaînes de caractères et nombre.

Bonne pratique : dans un tableau associatif les clés sont écrites en snake_case, sans caractère spécial, majuscule ou espace.

Dimensions et index

Les tableaux de la section précédente sont des tableaux à 1 dimension, car toutes les données sont au même « niveau », à la même « profondeur ». Un tableau peut contenir des nombres, des chaînes de caractères… mais il peut aussi contenir d’autres tableaux !

En reprenant l’exemple précédent :

$personne = [
    'prenom' => 'John',
    'nom' => 'Doe',
    'age' => 30,
    'profession' => 'PHP Expert',
    'skills' => ['PHP', 'POO', 'HTML', 'CSS']
];

Sur ma clé « skills », la valeur est un tableau, j’ai donc une seconde dimension à mon tableau.

Cela fonctionne aussi pour les tableaux non associatifs :

$morpion = [
   ['X', 'O', 'X'],
   ['O', 'X', 'X'],
   ['X', 'O', 'O'],
];

Pour accéder aux valeurs, je dois utiliser les « index » de mon tableau, entre crochets. Dans un tableau plat, les index sont gérés automatiquement, ce sont des valeurs entières, qui commencent à zéro. Voici des exemples en reprenant les variables déclarées plus haut :

echo $nombres[0]; // Affiche 1
echo $nombres[2]; // Affiche 3

echo $mots[1]; // Affiche "était"

Pour un tableau associatif, l’index correspond à la clé qu’on a définie manuellement.

echo $personne['prenom']; // Affiche "John"
echo $personne['age']; // Affiche 30

Bonne pratique : les tableaux associatifs permettent de bien identifier les données stockées et donc d’avoir un code très lisible. Il est plus facile de comprendre ce que contient $personne[‘prenom’] que $personne[0].

S’il y a plusieurs dimensions, on va cumuler les [] selon la dimension :

echo $profession['skills'][1]; // Affiche "POO"
echo $morpion[1][1]; // Affiche "X"

Comment créer et remplir un tableau PHP ?

Tableau vide

Dans les exemples précédents, on initialise tout de suite un tableau « rempli ». Mais on peut créer des tableaux vides, puis les remplir ensuite :

$tableau = []; // Tableau vide

Remplir un tableau, élément par élément

On peut ajouter les éléments un par un, de 2 façons :

$tableau[] = 1; // Avec les crochets
array_push($tableau, 1); // Avec la fonction array_push

Pour initialiser un tableau associatif, on va pouvoir créer une clé à la volée de cette façon :

$tableau['nouvelle_cle'] = 1;

Pour mettre à jour une valeur dans un tableau on utilisera l’index correspondant :

$tableau[1] = 2;
$tableau['nouvelle_cle'] = 2;
$morpion[1][1] = 'O'; // Comme ça je gagne ;)

Point d’attention : si la clé n’existe pas, aucune erreur ne sera retounée car PHP va donc créer un nouvel élément dans le tableau (cf. points précédents).

Remplir un tableau de façon dynamique

On peut utiliser une boucle, si par exemple je veux un tableau avec les 100 premiers entiers :

$tableau = [];
for ($i = 1; $i <= 100; $i++) {
    $tableau[] = $i;
}
// $tableau va contenir [1, 2, 3, ..., 100];

// Attention à bien gérer l'initialisation et la condition d'arrêt :
for ($i = 1; $i <= 100; $i++) {} // => [1, 2, 3, ..., 100] 100 éléments
for ($i = 0; $i <= 100; $i++) {} // => [0, 1, 2, ..., 100] 101 éléments
for ($i = 1; $i < 100; $i++) {} // => [1, 2, 3, ..., 99] 99 éléments
for ($i = 0; $i < 100; $i++) {} // => [0, 1, 2, ..., 99] 100 éléments

On peut imaginer des traitements + complexes dans la boucle.

La même chose peut être réalisé avec la fonction range :

$tableau = range(1, 100);

// Le pas (step) peut également être géré :
$tableau = range(0, 100, 2);
// $tableau va contenir [0, 2, 4, 6, ..., 98, 100]

Il existe 2 autres fonctions qui permettent de remplir un tableau de façon dynamique : array_fill et array_fill_keys :

$tableau = array_fill(
   0, // Index de départ
   100, // Nombre d'éléments
   'OK' // Valeur répétée
);
// $tableau va contenir ['OK', 'OK', 'OK', ... 'OK'] 100 fois, des index 0 à 99

//$keys est un tableau qui contient les clés que je vais utiliser
$keys = ['prenom', 'nom', 'profession'];

// Remplissage de $tableau
$tableau = array_fill_keys(
   $keys, // Les clés, index du tableau
   'text example' // Valeur répétée
);

// $tableau va contenir ['prenom' => 'text example', ..., 'profession' => 'text example']

Comment trier un tableau PHP ?

Il y a 3 façons de trier un tableau.

Tri d’un tableau selon les valeurs

On va utiliser les fonctions sort (ordre croissant) ou rsort (ordre décroissant). Le « r » signifie « reverse ». sort et rsort fonctionnent par référence :

$tableau = [3, 5, 1, 7, 2, 4, 6];
sort($tableau); // Et non $tableau = sort($tableau)
// $tableau contiendra [0 => 1, 1 => 2, ..., 6 => 7]

En utilisant sort, les index du tableau sont recréés au moment du tri. Si on veut conserver les index, on utilisera asort ou arsort. Le « a » signifie « associative ».

$tableau = [3, 5, 1, 7, 2, 4, 6];
asort($tableau); // Et non $tableau = asort($tableau)
// $tableau contiendra [2 => 1, 4 => 2, ..., 3 => 7]

Tri d’un tableau selon les clés

On va utiliser les fonctions ksort ou krsort. Le « k » signifie « keys ».

Tri sur mesure grâce à une fonction

Imaginons que j’ai plusieurs « personnes », structurées comme au début de cet article. Je veux les ordonner selon leur âge. Je dois donc les trier selon une valeur précise, je ne peux donc ni utiliser sort ni ksort, il va falloir que je précise que c’est la clé « age » que je veux utiliser pour mon tri.

Pour cela, on va créer une fonction dédiée, et utiliser un opérateur particulier : <=>

function triSelonAge(array $personne1, array $personne2): int
{
   return $personne1['age'] <=> $personne2['age'];
}

L’opérateur <=> va retourner 0, 1 ou -1 :

  • 0 si les éléments sont égaux
  • 1 si le premier élément est le plus grand
  • -1 si le premier élément est le plus petit

Une fois cette fonction créée, on va pouvoir l’appeler pour trier notre tableau :

$personnes = [
   [
      'age' => 28,
      ...
   ],
   [
      'age' => 30,
      ...
   ],
   [
      'age' => 27,
      ...
   ],
];

usort($personnes, 'triSelonAge'); // Encore un fonctionnement par référence

On peut aussi créer une fonction, dite anonyme, directement dans usort :

usort($personnes, function($a, $b) {
   return $a['age'] <=> $b['age'];
});

Comment comparer des tableaux PHP ?

Vérifier qu’un tableau est vide (ou pas)

On a pour habitude d’utiliser la fonction empty pour vérifier qu’un tableau est vide ou non :

if (empty($tableau)) {
   // ...
}

Mais si on regarde la documentation de PHP, on réalise que empty va aussi vérifier si la variable existe ou non, et retourner simplement false si elle n’existe pas. Ce qui peut engendrer des erreurs si jamais le tableau n’a pas été initialisé.

Du coup, c’est une bonne pratique d’utiliser la comparaison stricte par rapport à un tableau vide :

if ($tableau === []) {
   // ...
}

ou 

if ($tableau !== []) {
   // ...
}

Comparer des tableaux remplis

On n’y pense pas toujours mais on peut comparer des tableaux plus ou moins complexes entre eux :

if ($tableauComplexe1 === $tableauComplexe2) {
   // Il faut que toutes les clés et valeurs soient identiques
}

On peut également faire des choses comme ça :

if ($monTableau === range(1, 5)) {
   // Je vérifie que mon tableau contient [1, 2, 3, 4, 5]
}

Comment rechercher des clés ou valeurs dans un tableau PHP ?

Vérifier la présence d’une clé : isset ou array_key_exists ?

On a vu + haut comment accéder à la valeur d’un tableau. Mais si je veux accéder à $tableau[‘cle’] mais que l’index « cle » n’existe pas, PHP va déclencher une erreur. Il est donc souvent question de s’assurer qu’un index existe avant de vouloir accéder à la valeur correspondante. Il y a 2 principales possibilités : isset ou array_key_exists, regardons un peu les différences :

// On crée un tableau
$tableau = [
	'cle' => 'valeur'
];

isset($tableau['cle']); // => true
array_key_exists('cle', $tableau); // true

isset($tableau['autre_cle']); // => false
array_key_exists('autre_cle', $tableau); // false

Jusque là, tout va bien, les 2 fonctions sont équivalentes. Si la clé existe, elles renvoient true, si elle n’existe pas elles renvoient false.

Maintenant selon les valeurs :

// On crée un tableau, avec une clé, mais dont la valeur est null
$tableau = [
	'cle' => null
];

isset($tableau['cle']); // => false
array_key_exists('cle', $tableau); // true

$test = null;
isset($test); // false

Cette fois-ci, les 2 fonctions ne renvoient plus la même chose. isset renvoie en effet false quand il rencontre une valeur null. Alors que array_key_exists renvoie toujours true car la clé existe bien et qu’il ne vérifie pas la valeur contenue.

Une dernière différence selon l’existence ou non du tableau :

// Pas de tableau créé

isset($pasDeTableau['cle']); // false
array_key_exists('cle', $pasDeTableau); // Déclenche une erreur

Le fait que $pasDeTableau n’existe pas ne pose pas de problème à la fonction isset qui va donc renvoyer false. Par contre, array_key_exists a besoin d’un tableau comme paramètre et va donc cette fois-ci déclencher une erreur.

Bonne pratique : Il vaut mieux donc utiliser array_key_exists quand on vérifie la présence d’une clé dans un tableau, car isset peut présenter quelques effets de bord qui pourraient être complexes à détecter.

Rechercher une aiguille dans une botte de foin

PHP est parfois critiquer car l’ordre des paramètres d’une fonction change d’une fonction à une autre. C’est notamment vrai dans les fonctions liées aux tableaux. La documentation nomme toujours les paramètres « needle » et « haystack ». « needle » c’est toujours l’aiguille qu’on recherche dans la botte de foin « haystack ».

in_array

Comme son nom l’indique, on va rechercher si une valeur est « dans tableau » :


$lettres = ['a', 'b', 'c', 'd'];

in_array('a', $lettres); // => true
in_array('z', $lettres); // => false

array_search

Comme son nom l’indique un peu moins, array_search va retourner l’index de la première valeur correspondante trouvée :

$lettres = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

array_search('b', $lettres); // => 1
array_search('z', $lettres); // => false

Si la valeur n’existe pas, array_search renverra false.

Comment fusionner des tableaux PHP ?

La fusion de tableaux est un problème qui peut s’avérer plus complexe qu’il n’y paraît. PHP propose nativement 3 outils pour fusionner des tableaux : array_merge, array_merge_recursive et l’opérateur +.

Ce qui peut être complexe c’est qu’il ne se comporte pas de la même façon que l’on travaille sur un tableau « plat » (indexé numériquement) ou un tableau associatif.

Pour des tableaux plats, array_merge et array_merge_recursive vont se comporter de la même façon, en mettant bout à bout les différentes valeurs des tableaux et en reconstruisant les clés numériques de 0 à N… Par exemple :

$nombresA = [0, 1, 2]; // Indexé de 0 à 2
$nombresB = [3, 4, 5]; // Indexé de 0 à 2

array_merge($nombresA, $nombresB); // [0, 1, 2, 3, 4, 5] indexé de 0 à 5
array_merge_recursive($nombresA, $nombresB); // [0, 1, 2, 3, 4, 5] indexé de 0 à 5

// En précisant les index :
$nombresA = [3 => 0, 4 => 1, 5 => 2];
$nombresB = [10 => 3, 11 => 4, 12 => 5];

array_merge($nombresA, $nombresB); // [0, 1, 2, 3, 4, 5] indexé de 0 à 5
array_merge_recursive($nombresA, $nombresB); // [0, 1, 2, 3, 4, 5] indexé de 0 à 5

Ce sont des index numériques et ils sont donc reconstruits.

Avec des tableaux associatifs, ça se complique. En cas de conflit, array_merge va privilégier les données du « dernier » tableau ou du tableau « de droite ». array_merge_recursive va se comporter complètement différemment pour conserver toutes les valeurs rencontrées :

$personneA = [
    'prenom' => 'John',
    'nom' => 'Doe',
    'competence_unique' => 'Sport'
];

$personneB = [
    'prenom' => 'Jack',
    'nom' => 'Smith',
    'competence_speciale' => 'Musique'
];

array_merge($personneA, $personneB);
/*
Array
(
    [prenom] => Jack
    [nom] => Smith
    [competence_unique] => Sport
    [competence_speciale] => Musique
)
*/

array_merge_recursive($personneA, $personneB);
/*
Array
(
    [prenom] => Array
        (
            [0] => John
            [1] => Jack
        )

    [nom] => Array
        (
            [0] => Doe
            [1] => Smith
        )

    [competence_unique] => Sport
    [competence_speciale] => Musique
)
*/

Enfin, l’opérateur + va lui toujours comparer les clés et favoriser les valeurs du « premier » tableau, du tableau « de gauche ». On aura donc :

// Index identiques
$nombresA = [0, 1, 2];
$nombresB = [3, 4, 5];

$nombresA + $nombresB; // [0, 1, 2] puisque les index 0, 1, 2 sont communs entre les 2 tableaux, ce sont les valeurs du premier tableau qui sont conservées.

// Index différents
$nombresA = [3 => 0, 4 => 1, 5 => 2];
$nombresB = [10 => 3, 11 => 4, 12 => 5];

$nombresA + $nombresB;
/*
Array
(
    [3] => 0
    [4] => 1
    [5] => 2
    [10] => 3
    [11] => 4
    [12] => 5
)
*/

// Tableau associatif
$personneA + $personneB;
/*
Array
(
    [prenom] => John
    [nom] => Doe
    [competence_unique] => Sport
    [competence_speciale] => Musique
)

Pour les conflits d'index, ce sont les valeurs "de gauche" qui sont conservées.
*/

Précision : les exemples ci-dessus sont faits avec 2 tableaux. Mais toutes ces fonctions et opérateur permettent de fusionner autant de tableaux que nécessaire.

Bonne pratique : pas de array_merge dans une boucle

Pour des raisons de performances, on évitera au maximum d’avoir un array_merge dans une boucle. Explications et exemple de code :

Aller + loin

D’autres contenus sur Tainix te permettront de voir d’autres concepts liés aux tableaux en PHP :

Des challenges pour mettre en pratique ?

Voici quelques challenges qui te feront manipuler des tableaux :


Qui a codé ce superbe contenu ?

Keep learning

Autres contenus à découvrir


Ta newsletter chaque mois

Corrigés, challenges, actualités, veille technique... aucun spam.