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 :
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