Créa-blog

#100JoursPourCoder
Projet Créa-code

Ressources pour développeur web

Théme de la semaine : PHP version 8.5

Fonction anonyme et closure avec PHP 8.5 : Guide complet !

⏱️ Temps de lecture estimé : 8 minutes
Accueil PHP 8 Fonction anonyme et closure avec PHP 8.5 : Guide complet !

Vous avez sans doute déjà entendu parler de fonction anonyme, aussi appelées closure. Ces petits bouts de code, discrets en apparence, ont transformé la manière d’écrire du PHP depuis plusieurs années. Et avec PHP 8.5, les fonctions anonyme et closure deviennent plus puissantes que jamais, surtout quand elles se marient avec le fameux opérateur pipe (|>), qui rend leur utilisation encore plus fluide.

Mais avant d’aller trop vite, commençons par le début. Si vous débutez en PHP, vous vous demandez peut-être : “Une fonction anonyme, c’est quoi exactement ? Pourquoi en aurais-je besoin si je peux déjà créer des fonctions normales ?”

C’est une excellente question. Imaginez une fonction, mais sans nom. Oui, c’est aussi simple que ça. Une fonction anonyme est une fonction créée à la volée, souvent pour être utilisée dans l’instant, sans avoir besoin d’être déclarée ailleurs dans votre code.

Dit autrement, une fonction anonyme, c’est un peu comme un coup de main rapide dans votre code. Vous n’avez pas envie d’appeler un collègue pour l’occasion (autrement dit, créer une fonction entière dans un fichier séparé), alors vous l’écrivez directement sur place, au moment où vous en avez besoin.

Et vous allez voir : ces petites fonctions sans nom peuvent rendre votre code beaucoup plus lisible, compact et élégant.

Une fonction anonyme ou closure, c’est quoi concrètement ?

Prenons un exemple très simple. Imaginons que vous vouliez afficher “Bonjour Alban” à l’écran. Avec une fonction classique, vous feriez :

function direBonjour($nom) {
    return "Bonjour $nom";
}

echo direBonjour("Alban");

Simple et efficace. Mais si cette fonction n’est utilisée qu’une seule fois dans votre code, la déclarer ainsi est un peu lourd. Avec une fonction anonyme, vous pouvez l’écrire directement dans une variable :

$direBonjour = function($nom) {
    return "Bonjour $nom";
};

echo $direBonjour("Alban");

Regardez bien : pas de mot-clé function direBonjour, pas de nom, juste function(...) { ... };.

Le point-virgule final est important : c’est ce qui termine la création de la fonction avant qu’elle soit stockée dans la variable $direBonjour.

Désormais, $direBonjour est une fonction. Oui, une vraie fonction PHP que vous pouvez appeler quand vous voulez.

Pourquoi utiliser une fonction anonyme ou closure ?

Vous pourriez penser que ce n’est qu’une autre manière d’écrire la même chose. Mais dans la pratique, les closures deviennent très utiles dès que vous travaillez avec des fonctions de rappel (callbacks).

Les callbacks, ce sont ces fonctions qu’on transmet à d’autres fonctions pour qu’elles les exécutent plus tard. Un exemple typique : array_maparray_filter, ou encore usort.

Prenons le cas d’un tableau de prénoms :

$prenoms = ["Alban", "marie", "Julien", "sophie"];

Supposons que vous vouliez mettre la première lettre de chaque prénom en majuscule. Sans fonction anonyme ou closure, il faudrait définir une fonction séparée :

function capitaliser($nom) {
    return ucfirst($nom);
}

$prenoms = array_map("capitaliser", $prenoms);

Avec une fonction anonyme, vous pouvez tout écrire directement dans la même ligne :

$prenoms = array_map(function($nom) {
    return ucfirst($nom);
}, $prenoms);

C’est plus court, plus clair, et vous n’avez pas besoin de polluer votre code avec une fonction temporaire que vous n’utiliserez qu’une seule fois. C’est un peu comme sortir un tournevis de votre poche juste pour resserrer une vis, au lieu d’aller chercher toute la boîte à outils.

Les closures et les variables du contexte

Une des forces des fonctions anonymes, c’est qu’elles peuvent “emporter avec elles” des variables qui existent en dehors de leur portée. Pour cela, PHP utilise le mot-clé use.

Pour en savoir plus, consultez notre guide sur La portée des variables en PHP.

Prenons un exemple concret. Vous voulez afficher un message avec un préfixe, par exemple : “Note : Attention aux majuscules”.

$prefixe = "Note : ";

$afficher = function($message) use ($prefixe) {
    echo $prefixe . $message;
};

$afficher("Attention aux majuscules");

Résultat :

Note : Attention aux majuscules

Le mot-clé use indique que la fonction anonyme a besoin de cette variable $prefixe définie à l’extérieur. Sans lui, la fonction ne connaîtrait pas $prefixe, car chaque fonction en PHP a sa propre portée (c’est-à-dire son petit monde privé).

Les arrow functions : une version compacte des closures

Depuis PHP 7.4, le langage a introduit une version plus courte des fonctions anonymes : les arrow functions (fonctions fléchées). Elles utilisent la syntaxe fn() au lieu de function(), et elles sont parfaites pour des opérations simples d’une seule ligne.

Reprenons l’exemple précédent avec array_map :

$prenoms = ["alban", "marie", "julien"];

$prenoms = array_map(fn($nom) => ucfirst($nom), $prenoms);

Ici, pas besoin de return ni de use. Les arrow functions héritent automatiquement des variables du contexte et renvoient directement le résultat de l’expression.

C’est un peu comme une version “express” des closures. Mais attention : elles ne remplacent pas totalement les fonctions anonymes classiques, car elles ne peuvent contenir qu’une seule instruction.

Pour en savoir plus, consultez notre tutoriel sur Les paramètres de fonction et les retour en PHP.

Les closures et le pipe operator en PHP 8.5

Si vous avez lu notre guide précédent sur le pipe operator (|>) de PHP 8.5, vous savez qu’il permet de chaîner les transformations d’une valeur de manière fluide. Eh bien, les closures s’y intègrent parfaitement.

Prenons un exemple très simple. On veut transformer une phrase en majuscules, puis compter le nombre de caractères.

Sans pipe :

$result = strlen(strtoupper(trim($phrase)));

Avec pipe :

$result = $phrase
    |> trim(_)
    |> (fn($x) => strtoupper($x))(_)
    |> strlen(_);

Ici, (fn($x) => strtoupper($x))(_) est une arrow function utilisée directement dans le pipe. C’est élégant, court et lisible. Les closures deviennent alors de petits maillons dans une chaîne de transformations de données.

C’est cette synergie entre les deux nouveautés qui rend PHP 8.5 si agréable à utiliser. Vous pouvez traiter vos données comme si elles suivaient un petit circuit bien ordonné, où chaque closure joue son rôle avant de passer le relais.

Un exemple concret dans la vraie vie

Imaginons que vous développiez un petit site pour votre entreprise, et que vous deviez formater les titres des pages pour les afficher dans des URL propres (les fameux slugs).

Vous voulez :
– retirer les accents,
– remplacer les espaces par des tirets,
– passer tout en minuscules.

Avant PHP 8.5, cela aurait donné quelque chose comme :

function slugify($texte) {
    $texte = remove_accents($texte);
    $texte = str_replace(' ', '-', $texte);
    return strtolower($texte);
}

Avec le pipe et les closures, votre code devient presque poétique :

$slug = $titre
    |> (fn($x) => remove_accents($x))(_)
    |> (fn($x) => str_replace(' ', '-', $x))(_)
    |> strtolower(_);

Et le résultat est exactement le même. Mais la lisibilité est incomparable. On comprend d’un coup d’œil le cheminement de la donnée.

Une petite anecdote pour souffler

Quand les closures sont apparues en PHP 5.3, beaucoup de développeurs les ont snobées. Certains disaient : “C’est juste du sucre syntaxique, ça ne sert à rien.” Et pourtant, quelques années plus tard, impossible d’imaginer un projet sans elles.

C’est un peu comme les téléphones à écran tactile au début. Tout le monde riait de l’idée de taper sur une vitre. Et aujourd’hui ? Essayez de retrouver un téléphone à touches physiques, pour voir. Les closures, c’est pareil : une fois qu’on y a goûté, impossible de revenir en arrière.

Les closures et les objets : un duo sous-estimé

Jusqu’ici, nous avons utilisé les fonctions anonymes avec des variables ou des tableaux, mais elles peuvent aussi interagir avec des objets. C’est d’ailleurs l’un des points forts de PHP : même dans une approche orientée objet, on peut profiter de la souplesse des closures.

Formation web et informatique - Alban Guillier - Formateur

Des formations informatique pour tous !

Débutant ou curieux ? Apprenez le développement web, le référencement, le webmarketing, la bureautique, à maîtriser vos appareils Apple et bien plus encore…

Formateur indépendant, professionnel du web depuis 2006, je vous accompagne pas à pas et en cours particulier, que vous soyez débutant ou que vous souhaitiez progresser. En visio, à votre rythme, et toujours avec pédagogie.

Découvrez mes formations Qui suis-je ?

Pour découvrir et apprendre, consultez notre tutoriel complet sur La POO en PHP.

Prenons un exemple concret. Imaginons une classe Utilisateur :

class Utilisateur {
    public $nom;

    public function __construct($nom) {
        $this->nom = $nom;
    }
}

Et maintenant, imaginons une closure qui doit afficher un message personnalisé pour cet utilisateur :

$afficherMessage = function() {
    echo "Bienvenue, " . $this->nom;
};

Si vous exécutez ce code tel quel, il plantera. Pourquoi ? Parce que par défaut, une closure n’a pas accès à $this, même si elle est définie à proximité d’un objet.

Pour résoudre cela, PHP propose une méthode magique : bindTo(). Elle permet de lier une closure à un objet existant.

$utilisateur = new Utilisateur("Alban");
$messageLie = $afficherMessage->bindTo($utilisateur, Utilisateur::class);
$messageLie();

Résultat :

Bienvenue, Alban

En réalité, cette méthode “attache” la closure à l’instance $utilisateur. Ainsi, à l’intérieur de la fonction anonyme, $this fait désormais référence à cet objet. C’est une manière élégante de dynamiser vos scripts, par exemple pour des tests, des traitements personnalisés ou des callbacks dans vos classes.

Utiliser des closures dans vos objets PHP 8.5

Les closures peuvent également être membres d’une classe. Cela peut paraître étrange au début, mais c’est très utile pour stocker des fonctions temporaires, par exemple dans des systèmes de validation ou des filtres.

Prenons une classe simple de gestion de texte :

class TexteProcessor {
    public $filtre;

    public function __construct(callable $filtre) {
        $this->filtre = $filtre;
    }

    public function traiter($texte) {
        return ($this->filtre)($texte);
    }
}

Et maintenant, vous pouvez créer une instance avec une closure en paramètre :

$processeur = new TexteProcessor(function($texte) {
    return strtoupper(trim($texte));
});

echo $processeur->traiter("   php 8.5 et les closures   ");

Résultat :

PHP 8.5 ET LES CLOSURES

C’est une technique très puissante : votre classe devient capable d’appliquer n’importe quel traitement défini à la volée. En combinant cette logique avec le pipe operator, on obtient des pipelines ultra-flexibles et lisibles.

Closures et pipe : un mariage parfait

Avec PHP 8.5, la rencontre entre closure et pipe operator change la manière d’écrire vos scripts. Vous pouvez composer vos fonctions comme un véritable flux de données, où chaque closure devient une étape de transformation.

Regardons un exemple complet :

$texte = "   Créa-Blog : Les closures en PHP 8.5   ";

$resultat = $texte
    |> (fn($x) => trim($x))(_)
    |> (fn($x) => strtolower($x))(_)
    |> (fn($x) => str_replace(' ', '-', $x))(_)
    |> (fn($x) => urlencode($x))(_);

echo $resultat;

Résultat :

cr%C3%A9a-blog-:-les-closures-en-php-8.5

Chaque closure effectue une transformation : suppression des espaces, passage en minuscule, remplacement, puis encodage.

Votre code devient auto-documenté.

On comprend immédiatement la logique sans devoir lire dix lignes de variables intermédiaires. C’est aussi un excellent moyen d’éviter les erreurs de logique. Chaque étape est indépendante, et le |> enchaîne le tout avec fluidité.

Quand on y pense, le pipe est à PHP ce que la ponctuation est à une phrase : il donne le rythme et clarifie le sens.

Une approche fonctionnelle de PHP

Ce qu’apporte réellement le couple pipe + closures, c’est une manière plus fonctionnelle d’écrire du PHP. Plutôt que de manipuler directement les états ou les variables globales, on transforme les données en douceur, comme un flux continu.

Cela permet de réduire les effets de bord, ces petites erreurs sournoises qui apparaissent quand une variable change sans qu’on le veuille. Avec des closures pures (c’est-à-dire sans effet externe), chaque fonction devient prévisible : la même entrée donne toujours la même sortie.

En pratique, cela rend vos programmes :

  • plus lisibles,
  • plus faciles à tester,
  • et plus fiables.

Et même si vous débutez, cette manière d’écrire du code vous aide à structurer votre pensée. Vous n’êtes plus dans une suite de “tâches à exécuter”, mais dans une “transformation de données”. C’est une nuance subtile, mais qui change tout dans la qualité de votre code.

Les erreurs fréquentes avec les closures

Comme tout outil puissant, les closures ont leurs petits pièges. Voyons les plus courants :

1. Oublier que use copie la valeur
Lorsqu’on importe une variable extérieure avec use, elle est copiée au moment de la création de la closure. Si vous modifiez la variable ensuite, la closure n’en verra pas la mise à jour.

Exemple :

$prefixe = "Note : ";
$closure = function($message) use ($prefixe) {
    echo $prefixe . $message;
};
$prefixe = "Attention : ";
$closure("Ceci ne changera pas !");

Résultat :

Note : Ceci ne changera pas !

Pourquoi ? Parce que $prefixe a été copié dans la closure dès sa création. Pour contourner cela, on peut passer la variable par référence :

$closure = function($message) use (&$prefixe) {
    echo $prefixe . $message;
};

Désormais, tout changement de $prefixe sera pris en compte.

2. Tenter d’utiliser $this dans une closure statique
Si vous définissez une closure avec le mot-clé static, elle ne peut pas accéder à $this. Cela évite des erreurs de contexte, mais peut surprendre.

3. Abuser des closures dans les boucles
Les closures créées à la volée dans une boucle peuvent vite devenir illisibles.
Il faut savoir doser. Le but n’est pas de transformer tout votre code en enchaînement de closures, mais de les utiliser là où elles simplifient réellement la lecture.

L’évolution des closures : petit retour en arrière

Pour replacer les choses dans leur contexte, les fonctions anonymes ne sont pas nées avec PHP 8.5. Elles existent depuis PHP 5.3 (2009). Mais au fil des versions, elles se sont enrichies, jusqu’à devenir incontournables.

Voici un rappel de leur évolution (que vous pouvez intégrer à votre Créa-Blog) :

VersionÉvolution cléExemple court
PHP 5.3Apparition des fonctions anonymesfunction($x){return $x*2;}
PHP 5.4Ajout du mot-clé usefunction($x) use($y){...}
PHP 7.4Introduction des arrow functions (fn)fn($n)=>$n*2
PHP 8.5Intégration fluide avec le pipe operator|>

Chaque étape a contribué à rendre PHP plus moderne et plus agréable à écrire.
Le langage, autrefois jugé “vieillot”, adopte désormais les principes des langages fonctionnels modernes tout en restant accessible.

Quand j’ai découvert les closures, je m’en suis servi un peu partout, même là où il ne fallait pas. Mon code ressemblait à un mille-feuille de fonctions anonymes, impossible à déboguer…

Les closures sont fantastiques, mais leur force réside dans leur sobriété. Elles simplifient votre code quand elles remplacent trois lignes inutiles, pas quand elles en ajoutent trente.


La liberté dans la simplicité

Les fonction anonyme et closure incarnent une nouvelle ère pour le PHP moderne. Elles permettent d’écrire un code plus lisible, plus expressif et plus intelligent.

Avec PHP 8.5 et l’opérateur pipe, elles s’intègrent naturellement dans une logique fluide, presque poétique : chaque fonction devient une étape dans la transformation de vos données.

Mais au-delà de la technique, les closures enseignent une leçon de fond : celle de la clarté. Elles nous rappellent qu’un code lisible n’est pas un luxe, mais une marque de respect — envers soi-même et envers ceux qui liront votre travail demain.

Alors expérimentez, testez, amusez-vous. Créez de petites fonctions à la volée, jouez avec le pipe operator, explorez cette nouvelle manière de penser le code. Et surtout, souvenez-vous : la beauté du PHP moderne ne vient pas de sa complexité, mais de sa capacité à dire les choses simplement.