Les fonctions anonymes

Résumé Support Quiz

Les fonctions anonymes, aussi appelées closures, permettent de créer des fonctions sans leur donner de nom global. C'est pratique lorsqu'une fonction ne sert qu'à un endroit précis, par exemple pour trier ou filtrer un tableau avec une logique personnalisée.

Créer une fonction anonyme

Une fonction classique doit avoir un nom et devient disponible globalement. Avec une fonction anonyme, on garde la même syntaxe de base, mais sans nom après le mot-clé function.

$maFonction = function (string $name) { return "Salut $name"; };

Ici, la fonction est stockée dans une variable. Cette variable contient une closure et on peut l'appeler comme une fonction classique.

echo $maFonction('Jean'); // Salut Jean

Attention, contrairement à une déclaration de fonction classique, l'affectation dans une variable doit se terminer par un point-virgule.

Comprendre les callables

Certaines fonctions PHP attendent un callable, c'est-à-dire quelque chose que PHP peut appeler comme une fonction. Cela peut être :

  • le nom d'une fonction sous forme de chaîne de caractères.
  • une méthode d'objet sous forme de tableau.
  • une closure.

Les closures deviennent intéressantes dans ce contexte, car elles permettent de définir une logique directement à l'endroit où elle est utilisée, sans créer une fonction globale qui ne servira qu'une seule fois.

Trier un tableau avec usort()

Un cas classique d'utilisation est le tri d'un tableau complexe. Imaginons un tableau d'élèves, chaque élève étant représenté par un tableau contenant son nom et son âge. L'objectif est de trier les élèves par âge croissant.

La fonction usort() permet de trier un tableau avec une fonction de comparaison personnalisée.

$eleves = [ ['nom' => 'Jean', 'age' => 20], ['nom' => 'Marc', 'age' => 21], ['nom' => 'Anne', 'age' => 18], ]; usort($eleves, function ($eleve1, $eleve2) { return $eleve1['age'] - $eleve2['age']; }); var_dump($eleves);

La fonction passée à usort() reçoit deux éléments à comparer. Elle doit retourner :

  • un entier inférieur à 0 si le premier élément doit être placé avant le second.
  • 0 si les deux éléments sont considérés comme équivalents.
  • un entier supérieur à 0 si le premier élément doit être placé après le second.

Dans le cas de valeurs numériques, soustraire les deux âges permet d'obtenir directement ce comportement. Si on compare des chaînes de caractères, il faudra utiliser une autre logique de comparaison.

usort() modifie le tableau passé en premier paramètre. C'est important à retenir, car le tableau original sera réorganisé.

Utiliser une variable extérieure avec use

Une closure n'a pas automatiquement accès aux variables définies autour d'elle. Comme pour une fonction classique, son contexte est séparé.

Si on veut choisir dynamiquement la clé utilisée pour trier le tableau, ce code ne fonctionnera pas directement :

$key = 'age'; usort($eleves, function ($eleve1, $eleve2) { return $eleve1[$key] - $eleve2[$key]; });

La variable $key n'existe pas à l'intérieur de la closure. Pour l'utiliser, on doit la transmettre avec le mot-clé use.

$key = 'age'; usort($eleves, function ($eleve1, $eleve2) use ($key) { return $eleve1[$key] - $eleve2[$key]; });

Cette syntaxe indique que la fonction anonyme doit utiliser une variable déjà définie dans le contexte extérieur.

Retourner une closure depuis une fonction

Une fonction peut aussi retourner une closure. Cela permet de générer une fonction de comparaison à partir d'un paramètre.

function sorterByKey(string $key): Closure { return function ($a, $b) use ($key) { return $a[$key] - $b[$key]; }; } usort($eleves, sorterByKey('age'));

Ici, sorterByKey('age') retourne une fonction anonyme utilisable par usort(). En changeant la clé, on peut réutiliser la même logique pour trier par âge ou par moyenne.

On peut aussi encapsuler directement le tri dans une fonction qui retourne un nouveau tableau trié.

function sortByKey(array $items, string $key): array { usort($items, function ($a, $b) use ($key) { return $a[$key] - $b[$key]; }); return $items; } $elevesTries = sortByKey($eleves, 'age');

Dans cette version, on évite de modifier directement la variable originale et on récupère le résultat dans un nouveau tableau.

Filtrer un tableau avec array_filter()

Les closures sont aussi utiles avec array_filter(). Cette fonction parcourt les éléments d'un tableau et conserve uniquement ceux pour lesquels la fonction utilisateur retourne true.

$elevesAvecLaMoyenne = array_filter($eleves, function ($eleve) { return $eleve['moyenne'] > 10; });

Dans cet exemple, seuls les élèves ayant une moyenne supérieure à 10 sont conservés. Si on inverse la condition avec < 10, on récupère au contraire les élèves qui n'ont pas la moyenne.

Contrairement à usort(), array_filter() ne prend pas le tableau par référence. Elle retourne donc un nouveau tableau filtré.

Utiliser une méthode comme callable

Quand on travaille dans une classe, un callable peut aussi pointer vers une méthode de l'objet. Pour cela, on utilise un tableau contenant l'objet et le nom de la méthode.

class Demo { private array $eleves = []; public function bonsEleves(): array { return array_filter($this->eleves, [$this, 'filterFunction']); } private function filterFunction(array $eleve): bool { return $eleve['moyenne'] > 10; } }

Ici, [$this, 'filterFunction'] indique à PHP d'appeler la méthode filterFunction() sur l'objet courant. Cette forme est pratique lorsqu'on préfère isoler la logique dans une méthode plutôt que de l'écrire directement dans une closure.

Ressources