Récursivité : afficher toutes les clés et valeurs d’un objet ou tableau multidimensionnel en PHP
Cela faisait si longtemps que je voulais présenter des exemples de récursivité (ou "récursion") que je profite de ce tutoriel vidéo pour vous en montrer un exemple fort pratique et intéressant en PHP : le parcours et l'affichage de l'ensemble des données d'un tableau à "n" dimensions, et quel que soit le type de valeur qu'il contient (objet, chaîne de caractère, booléen et numérique par exemple).
Qu'est-ce que la récursivité ?
La récursivité est un principe de programmation qui vise à utiliser en boucle une même fonction jusqu'à ce qu'une issue favorable soit trouvée. Le cas le plus connu est sûrement la suite de Fibonacci pour laquelle chaque nombre de la suite est la somme des deux nombres précédents. En d'autres termes, la récursivité appelle dans une fonction cette même fonction, et ainsi de suite.
En effet, il arrive fréquemment de devoir parcourir les clés et valeurs de tableaux multidimensionnels (ou objets) à "n" dimensions pour retrouver des données spécifiques. Mais force est de constater que de faire des foreach dans des foreach peut très vite devenir barbant, et encore plus quand on ne sait pas combien de niveaux il faudra parcourir exactement.. C'est là tout l'enjeu de la récursivité ! ;-)
Alors, quoi de mieux qu'une fonction du type print_r() qui parcoure tous les niveaux de profondeur d'un tableau avec un affichage personnalisable ? L'idée est ici de pouvoir parcourir n'importe quel tableau ou objet PHP, quel que soit son niveau de profondeur, en remontant à chaque fois les clés et valeurs qui nous intéressent. Ainsi, l'affichage est plus lisible (enfin si on ne fait pas n'importe quoi ^^) qu'un print_r() ou un var_dump(). Ajoutons à cela que les fonctions que nous allons étudier vont automatiquement masquer les clés privées (private) et protégées (protected) en cas de parcours d'un objet, il ne restera donc que les valeurs utiles et publiques !
Quand le nombre de dimensions devient pharaonique...
Pour l'anecdote, j'utilise parfois les fonctions présentées ici (voir codes dans la conclusion ou dans la vidéo) quand j'utilise des API comme celles de Google ou de Twitter. Cela me permet rapidement de trouver les données qui m'intéressent, ou tout simplement de pouvoir rapidement rejoindre un niveau de profondeur donné. Voyez donc cela comme des fonctions permettant un gain de temps à l'usage, bien qu'on puisse s'en sortir avec des print_r() ou des var_dump() bien entendu dans la majorité des cas peu profonds.
Je vous invite donc à regarder la vidéo ou à passer directement à la conclusion pour retrouver les codes de 3 fonctions PHP permettent le parcours rapide de tableaux multidimensionnels :
- print_recursive() : fonction simple qui affiche toutes les clés => valeurs sur plusieurs niveaux de profondeur. C'est une sorte de print_r() avec un affichage plus simple et personnalisable si besoin (en changeant dans la fonction).
- print_recursive_tab() : même fonction si ce n'est qu'elle permet aussi de retourner un tableau pour chaque niveau de profondeur. Plus l'indice du tableau retourné est élevé, plus vous êtes dans les niveaux profonds. Cette fonction est surtout utile pour trouver des données parfois cachés à une dizaine de niveaux de profondeur (dans les API notamment, cela peut arriver).
- print_recursive_callback() : fonction qui permet d'appeler une fonction de rappel (callback) pour personnaliser l'affichage des données lors du parcours du tableau. C'est en théorie la fonction la plus pratique pour obtenir un résultat souhaitable.
Conclusion
J'espère que la vidéo vous a éclairé quelque peu sur l'usage des 3 fonctions d'affichage d'objets ou de tableaux multidimensionnels avec l'ensemble des clés et valeurs. Sans plus attendre, vous pouvez télécharger le fichier suivant qui contient les fonctions ainsi que l'exemple présenté dans la vidéo. Et si vous préférez, vous pouvez copier/coller chacune des fonctions ci-dessous.
print_recursive
La fonction print_recursive() prend jusqu'à 3 paramètres :
- le tableau ou objet PHP à parcourir et lire ;
- la mise en gras ou non des clés de tableaux (pour faciliter la lecture), via un booléen (true/false) ;
- le numéro de niveau de profondeur (normalement, laissez tel quel).
function print_recursive($tab = array(), $strong = false, $niveau = 0) { // Supprime les clés private et protected s'il s'agit d'un objet if(is_object($tab)) { $tab = get_object_vars($tab); } // Ajoute les sauts de ligne pour chaque niveau de profondeur (sauf le premier !) if($niveau != 0) { echo "<br/>"; } foreach($tab as $key => $value) { // Affichage des clés avec tabulation par niveau de profondeur if($strong === true) { echo str_repeat(" ", $niveau * 4)."<strong>".$key."</strong> => "; } else { echo str_repeat(" ", $niveau * 4).$key." => "; } // Vérifie si la valeur correspond elle-même à un tableau ou un objet if((is_array($value) || is_object($value))) { // Appel récursif de la fonction pour lire un autre niveau de profondeur print_recursive($value, $strong, $niveau + 1); continue; } // Affichage des valeurs (quand ce ne sont pas des tableaux/objets) echo $value."<br/>"; } }
print_recursive_tab
La fonction print_recursive_tab() retourne un tableau complet pour chaque niveau de profondeur du tableau. Plus vous ciblez un indice haut, plus vous obtenez des clés et valeurs d'une certaine profondeur. La fonction PHP prend jusqu'à 4 paramètres :
- le tableau ou objet PHP à parcourir et lire ;
- l'affichage ou non des données (comme la fonction print_recursive), via un booléen (true/false) ;
- la mise en gras ou non des clés de tableaux (pour faciliter la lecture), via un booléen (true/false) ;
- le numéro de niveau de profondeur (normalement, laissez tel quel).
function print_recursive_tab($tab = array(), $echo = false, $strong = false, $niveau = 0) { // Crée un tableau statique pour enregistrer chaque niveau de profondeur static $new_tab = array(); // Ajoute les sauts de ligne pour chaque niveau de profondeur (sauf le premier !) if($echo === true && $niveau != 0) { echo "<br/>"; } foreach($tab as $key => $value) { if($echo == true) { // Affichage des clés avec tabulation par niveau de profondeur if($strong === true) { echo str_repeat(" ", $niveau * 4)."<strong>".$key."</strong> => "; } else { echo str_repeat(" ", $niveau * 4).$key." => "; } } // Enregistre les données niveau de profondeur par niveau de profondeur if(!is_object($value)) { $new_tab[$niveau][$key] = $value; } else { $new_tab[$niveau][$key] = get_object_vars($value); } if((is_array($value) || is_object($value))) { // Appel récursif de la fonction pour lire un autre niveau de profondeur print_recursive_tab($value, $echo, $strong, $niveau + 1); continue; } if($echo == true) { // Affichage des valeurs (quand ce ne sont pas des tableaux/objets) echo $value."<br/>"; } } // Retourne le tableau pour chaque niveau de profondeur return $new_tab; }
print_recursive_callback
La fonction print_recursive_callback() permet de personnaliser l'affichage des résultats grâce à une fonction de rappel (callback). Bien sûr, vous n'avez pas une pleine liberté à cause de la récursivité de la fonction (qui empêche d'effectuer certains rendus), mais cela permet vraiment d'obtenir un résultat différent, comme le montrera la capture suivante basé sur l'exemple de la vidéo. La fonction PHP peut prendre jusqu'à 4 paramètres :
- le tableau ou objet PHP à parcourir et lire ;
- la fonction de rappel (callback) ;
- l'affichage ou non des clés de premiers niveaux (true/false) ;
- le numéro de niveau de profondeur (normalement, laissez tel quel).
function print_recursive_callback($tab = array(), $callback, $withKey = true, $niveau = 0) { // Supprime les clés private et protected s'il s'agit d'un objet if(is_object($tab)) { $tab = get_object_vars($tab); } foreach($tab as $key => $value) { if((is_array($value) || is_object($value))) { // Appel récursif de la fonction pour lire un autre niveau de profondeur if($withKey === true) { call_user_func($callback, $key, "", $niveau); } print_recursive_callback($value, $callback, $withKey, $niveau + 1); continue; } // Appel à la fonction de rappel avec quatre paramètres oblibatoires !!! if($withKey === true) { call_user_func($callback, $key, $value, $niveau); } else { call_user_func($callback, $key, $value, $niveau); } } }
Comparer les fonctions de lecture des objets et tableaux en PHP
Observez la capture finale ci-dessous qui affiche le même tableau multidimensionnel (contenant des objets) selon les fonctions utilisées. Cela élargit la panoplie des possibilités et permet de plus facilement parcourir les données en PHP, sans forcément faire appel au classique print_r() à qui il faut adjoindre des balises "pre" en HTML, ou à var_dump() parfois illisible quand la profondeur du tableau est vaste.