Fonctions anonymes

Les fonctions anonymes, aussi appelées fermetures ou closures permettent la création de fonctions sans préciser leur nom. Elles sont particulièrement utiles comme fonctions de rappel callable, mais leur utilisation n'est pas limitée à ce seul usage.

Les fonctions anonymes sont implémentées en utilisant la classe Closure.

Exemple #1 Exemples avec des fonctions anonymes

<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
return
strtoupper($match[1]);
},
'bonjour-le-monde');
?>

Les fonctions anonymes peuvent aussi être utilisées comme valeurs de variables. PHP va automatiquement convertir ces expressions en objets Closure. Assigner une fermeture à une variable est la même chose qu'une affectation classique, y compris pour le point-virgule final.

Exemple #2 Assignation de fonction anonyme à une variable

<?php
$greet
= function($name) {
printf("Bonjour %s\r\n", $name);
};

$greet('World');
$greet('PHP');
?>

Les fonctions anonymes peuvent hériter des variables du contexte de leur parent. Ces variables doivent alors être passées dans la construction de langage use. À partir de PHP 7.1, ces variables ne doivent pas inclure de superglobals, $this, ou des variables ayant le même nom qu'un paramètre. Une déclaration de type de retour pour la fonction doit être placé après la clause use.

Exemple #3 Héritage de variable depuis le contexte parent

<?php
$message
= 'hello';

// Pas de "use"
$example = function () {
var_dump($message);
};
$example();

// Hérite $message
$example = function () use ($message) {
var_dump($message);
};
$example();

// La valeur de la variable héritée est définie lorsque la fonction est
// définie non quand elle est appelée
$message = 'world';
$example();

// Réinitialisation de la variable message
$message = 'hello';

// Héritage par référence
$example = function () use (&$message) {
var_dump($message);
};
$example();

// Le changement de valeur dans le contexte parent est reflété lors de
// l'appel de la fonction.
$message = 'world';
$example();

// Les fonctions anonymes acceptent également des arguments classiques
$example = function ($arg) use ($message) {
var_dump($arg . ' ' . $message);
};
$example("hello");

// Return type declaration comes after the use clause
$example = function () use ($message): string {
return
"hello $message";
};
var_dump($example());
?>

Résultat de l'exemple ci-dessus est similaire à :

 Notice: Undefined variable: message in /example.php on line 6 NULL string(5) "hello" string(5) "hello" string(5) "hello" string(5) "world" string(11) "hello world" string(11) "hello world" 

À partir de PHP 8.0.0, la liste des variables hérité du contexte peut inclure une virgule trainante, qui sera ignoré.

L'héritage du contexte parent n'est pas la même chose que les variables de l'environnement global. Les variables globales existent dans le contexte global, qui est le même, quelle que soit la fonction qui s'exécute. Le contexte parent d'une fonction anonyme est la fonction dans laquelle la fonction a été déclarée (pas nécessairement celle qui appelle). Voyez l'exemple ci-dessous :

Exemple #4 Fonctions anonymes et contexte

<?php
// Un panier d'achat simple, qui contient une liste de produits
// choisis et la quantité désirée de chaque produit. Il inclut
// une méthode qui calcule le prix total des éléments dans le panier
// en utilisant une fonction de rappel anonyme.
class Panier
{
const
PRICE_BEURRE = 1.00;
const
PRICE_LAIT = 3.00;
const
PRICE_OEUF = 6.95;

protected
$products = array();

public function
add($product, $quantity)
{
$this->products[$product] = $quantity;
}

public function
getQuantity($product)
{
return isset(
$this->products[$product]) ? $this->products[$product] :
FALSE;
}

public function
getTotal($tax)
{
$total = 0.00;

$callback =
function (
$quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};

array_walk($this->products, $callback);
return
round($total, 2);
}
}

$mon_panier = new Panier;

// Ajout d'élément au panier
$mon_panier->add('beurre', 1);
$mon_panier->add('lait', 3);
$mon_panier->add('oeuf', 6);

// Affichage du prix avec 5.5% de TVA
print $mon_panier->getTotal(0.055) . "\n";
// Le résultat sera 54.29
?>

Exemple #5 Liage automatique de $this

<?php

class Test
{
public function
testing()
{
return function() {
var_dump($this);
};
}
}

$object = new Test;
$function = $object->testing();
$function();

?>

L'exemple ci-dessus va afficher :

 object(Test)#1 (0) { } 

Lorsque déclarée dans le contexte d'une classe, la classe courante est automatiquement liée, la rendant $this disponible dans le contexte de la fonction. Si ce liage automatique de la classe courante n'est pas souhaité, alors les fonctions anonymes statiques peuvent être utilisées à la place.

Les fonctions anonymes statiques

Les fonctions anonymes peuvent être déclarées statiquement. Ceci permet de ne pas lier automatiquement la classe courante à la fonction. Les objets peuvent aussi ne pas être liés lors de l'exécution.

Exemple #6 Tentative d'usage de $this dans une fonction anonyme statique

<?php

class Foo
{
function
__construct()
{
$func = static function() {
var_dump($this);
};
$func();
}
};
new
Foo();

?>

L'exemple ci-dessus va afficher :

 Notice: Undefined variable: this in %s on line %d NULL 

Exemple #7 Tentative de liage d'un objet à une fonction anonyme statique

<?php

$func
= static function() {
// function body
};
$func = $func->bindTo(new stdClass);
$func();

?>

L'exemple ci-dessus va afficher :

 Warning: Cannot bind an instance to a static closure in %s on line %d 

Historique

VersionDescription
7.1.0 Les fonctions anonymes peuvent ne pas se fermer sur les superglobals, $this, ou toute variable avec le même nom qu'un paramètre.

Notes

Note: Il est possible d'utiliser les fonctions func_num_args(), func_get_arg() et func_get_args() dans une fonction anonyme.

To Top