Un callable est une référence à une fonction ou une méthode qui est
passée à une autre fonction en tant qu'argument.
Elles sont représentées avec la déclaration de type callable.
Création de callables
Un callable est un type qui représente quelque chose qui peut être invoqué.
Les callables peuvent être passés en tant qu'arguments aux fonctions ou méthodes qui
attendent un paramètre callback ou ils peuvent être invoqués directement.
Le type callable ne peut pas être utilisé comme déclaration de type pour les
propriétés. A la place, utilisez une déclaration de type Closure.
Les callables peuvent être crées de plusieurs façons différentes :
Un object Closure peut être créer en utilisant
la syntaxe function anonyme,
la syntaxe function fléchée,
la syntaxe callable de première
classe, ou la méthode Closure::fromCallable().
Note:
La syntaxe callable de première
classe est disponible uniquement à partir de PHP 8.1.0.
Exemple #1
Exemple de callback utilisant une Closure
<?php
// Utilisant la syntaxe de fonction anonyme
$double1 = function ($a) {
return $a * 2;
};
// Utilisant la syntaxe callable de première classe
function double_function($a) {
return $a * 2;
}
$double2 = double_function(...);
// Utilisant la syntaxe de fonction fléchée
$double3 = fn($a) => $a * 2;
// Utilisant la méthode Closure::fromCallable
$double4 = Closure::fromCallable('double_function');
// Utilisant la closure comme callback pour
// doubler la taille de chaque élément dans notre range
$new_numbers = array_map($double1, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double2, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double3, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double4, range(1, 5));
print implode(' ', $new_numbers);
?>
Résultat de l'exemple ci-dessus en PHP 8.1 :
2 4 6 8 10
2 4 6 8 10
2 4 6 8 10
2 4 6 8 10
Un callable peut également être une string contenant le nom d'une fonction ou une méthode
statique.
N'importe quelle fonction intégrée ou définie par l'utilisateur peut être utilisée, à l'exception des constructions de langage
telles que : array(), echo,
empty(), eval(),
isset(),
list(), print ou
unset().
Les méthodes de classes statiques peuvent être utilisées sans instancier un
object de cette classe en créant soit un tableau avec
le nom de la classe à l'index 0 et le nom de la méthode à l'index 1, ou en utilisant
la syntaxe spéciale avec l'opérateur de résolution de portée
::, comme dans 'ClassName::methodName'.
Une méthode d'un object instancié peut être un callable
lorsqu'elle est fournie sous forme de tableau avec le object à l'index 0 et
le nom de la méthode à l'index 1.
La principale différence entre un objet Closure et le
type callable type est que l'objet Closure
est indépendant du scope et peut tous le temps est invoqué, alors qu'un type callable peut
être dépendant du scope et ne peut être invoqué directement.
Closure est la méthode préférée pour créer des callables.
Note:
Tandis que les objets Closure sont liés au scope
où ils sont créés, les callables référencant des méthodes de classes sous forme
de chaînes de caractères ou de tableaux sont résolus dans le scope où ils sont appelés.
Pour créer un callable à partir d'une méthode privée ou protégée, qui peut ensuite être
invoqué depuis l'extérieur de la classe, utilisez
Closure::fromCallable() ou la
syntaxe callable de
première classe
PHP permet la création de callables qui peuvent être utilisés en tant qu'argument
de callback mais qui ne peuvent pas être appelés directement.
Il s'agit de callables dépendants du contexte qui référencent une méthode de classe
dans la hiérarchie d'héritage d'une classe, par exemple
'parent::method' ou ["static", "method"].
Note:
Depuis PHP 8.2.0, les callables dépendants du contexte
sont dépréciés. Supprimez la dépendance au contexte en remplaçant
'parent::method' par
parent::class . '::method' ou utilisez la
syntaxe callable de
première classe.
Exemple #2
Appel de différents types de callables avec call_user_function()
<?php
// Un exemple de fonction de rappel
function my_callback_function() {
echo 'hello world!', PHP_EOL;
}
// Un exemple de méthode de rappel
class MyClass {
static function myCallbackMethod() {
echo 'Hello World!', PHP_EOL;
}
}
// Type 1: Callback simple
call_user_func('my_callback_function');
// Type 2: Appel de méthode de classe statique
call_user_func(['MyClass', 'myCallbackMethod']);
// Type 3: Appel de méthode d'objet
$obj = new MyClass();
call_user_func([$obj, 'myCallbackMethod']);
// Type 4: Appel de méthode de classe statique
call_user_func('MyClass::myCallbackMethod');
// Type 5: Appel de méthode de classe statique en utilisant le mot-clé ::class
call_user_func([MyClass::class, 'myCallbackMethod']);
// Type 6: Appel de méthode de classe statique relative
class A {
public static function who() {
echo 'A', PHP_EOL;
}
}
class B extends A {
public static function who() {
echo 'B', PHP_EOL;
}
}
call_user_func(['B', 'parent::who']); // deprecated as of PHP 8.2.0
// Type 7: Les objets implémentant __invoke peuvent être utilisés en tant que callables
class C {
public function __invoke($name) {
echo 'Hello ', $name;
}
}
$c = new C();
call_user_func($c, 'PHP!');
?>
L'exemple ci-dessus va afficher :
hello world!
Hello World!
Hello World!
Hello World!
Hello World!
Deprecated: Callables of the form ["B", "parent::who"] are deprecated in script on line 41
A
Hello PHP!
Note:
Notez que les fonctions de rappel enregistrées avec des fonctions comme call_user_func() et
call_user_func_array() ne seront pas appelées si une exception n'est pas interceptée alors
qu'elle a été lancée dans une précédente fonction de rappel.