« Le gabarit d’accueil personnalisé s’affiche toujours en dernier dans le sélecteur, jamais en premier comme prévu » : ce signalement, remonté par une cliente qui gérait elle-même l’ordre d’affichage de plusieurs gabarits personnalisés dans un menu déroulant du thème, a mis plusieurs jours à être reproduit de façon fiable, avant qu’un test isolé ne révèle un comportement systématique lié à un seul indice précis.
Symptôme : un ordre correct pour tous, sauf un
Le thème proposait un tableau $ordre_gabarits, déclaré dans functions.php, qui fixait l’ordre d’affichage souhaité des gabarits personnalisés dans un menu de navigation secondaire. Chaque gabarit devait apparaître à la position définie par cet ordre, sauf celui placé explicitement en première position, qui se retrouvait systématiquement relégué en toute fin de liste, quel que soit le contenu réel du tableau.
Diagnostic : un retour de fonction confondu avec un booléen

Le code responsable du tri s’appuyait sur array_search() pour retrouver la position déclarée d’un gabarit, avant de l’utiliser comme clé de tri :
foreach ( $gabarits as $gabarit ) {
$position = array_search( $gabarit->slug, $ordre_gabarits );
if ( $position ) {
$gabarit->ordre = $position;
} else {
$gabarit->ordre = 999;
}
}
array_search() renvoie l’indice de l’élément trouvé dans le tableau, ou false si l’élément est absent. Pour le premier élément du tableau $ordre_gabarits, cet indice vaut 0 — une valeur entière parfaitement valide, mais que PHP considère comme fausse dans un contexte booléen, exactement comme false lui-même. La condition if ( $position ) traitait donc ce cas comme un échec de recherche, et affectait au gabarit concerné l’ordre par défaut réservé aux éléments non trouvés.
Correctif : une comparaison stricte au type
Le correctif consiste à remplacer la comparaison implicite par une comparaison stricte, explicitement au type, pour distinguer 0 (une position valide) de false (une absence réelle) :
foreach ( $gabarits as $gabarit ) {
$position = array_search( $gabarit->slug, $ordre_gabarits );
if ( $position !== false ) {
$gabarit->ordre = $position;
} else {
$gabarit->ordre = 999;
}
}
Après ce changement, le gabarit d’indice 0 dans $ordre_gabarits retrouvait sa position réelle, et le tri final produisait l’ordre attendu pour l’ensemble des gabarits, sans exception.
Pourquoi ce bug est resté invisible aussi longtemps
La condition fautive fonctionnait correctement pour tous les indices supérieurs à zéro, qui restent évalués comme vrais dans un contexte booléen. Seul l’élément placé en première position du tableau déclenchait le comportement incorrect, ce qui explique pourquoi les tests menés en modifiant l’ordre des autres gabarits ne révélaient jamais le problème : il fallait spécifiquement placer un gabarit en tout premier pour l’observer.
Prévention pour la suite
- traiter systématiquement le retour de
array_search(),strpos()ouarray_key_first()avec une comparaison stricte au type, jamais avec une simple condition implicite ; - ajouter un test unitaire dédié qui place explicitement un élément en position 0, précisément parce que ce cas limite échappe facilement à une relecture rapide du code ;
- activer un niveau d’analyse statique du code qui signale les comparaisons implicites sur des fonctions dont le retour peut valoir zéro ou une chaîne vide en cas de succès.
Nous relisons systématiquement tout usage de
array_search(),strpos()ouarray_search()dans une revue de code, en cherchant explicitement l’absence d’un!== false: c’est l’un des rares réflexes de relecture qui a un rapport temps investi contre bugs évités aussi favorable.
Ce qu’il faut retenir
Ce bug n’avait rien d’exotique : il s’agit d’une des confusions les plus documentées du langage PHP, entre une valeur falsy légitime et une absence de résultat. Sa discrétion tenait uniquement au fait qu’il ne se manifestait que pour un seul indice précis d’un tableau, ce qui l’a rendu difficile à isoler tant que personne n’avait pensé à tester spécifiquement ce cas limite.