La syntaxe de callable de première classe est introduite à partir de PHP 8.1.0, comme une manière de créer des fonctions anonymes depuis des callable. Elle remplace la syntaxe des callables existante utilisant les chaînes et tableaux. L'avantage de cette syntaxe est qu'elle est accessible à l'analyse statique et utilise la portée du point où le callable est acquis.
La syntaxe CallableExpr(...)
est utilisée pour créer un objet
Closure depuis le callable.
CallableExpr
accepte toute expression qui peut être directement
appelée dans la grammaire de PHP :
Exemple #1 Syntaxe callable de première classe basique
<?php
class Foo {
public function method() {}
public static function staticmethod() {}
public function __invoke() {}
}
$obj = new Foo();
$classStr = 'Foo';
$methodStr = 'method';
$staticmethodStr = 'staticmethod';
$f1 = strlen(...);
$f2 = $obj(...); // invokable object
$f3 = $obj->method(...);
$f4 = $obj->$methodStr(...);
$f5 = Foo::staticmethod(...);
$f6 = $classStr::$staticmethodStr(...);
// traditional callable using string, array
$f7 = 'strlen'(...);
$f8 = [$obj, 'method'](...);
$f9 = [Foo::class, 'staticmethod'](...);
?>
Note:
Les
...
font partie de la syntaxe et ne sont pas une omission.
CallableExpr(...)
a les mêmes sémantiques que Closure::fromCallable().
C'est-à-dire, contrairement aux callables utilisant les chaînes et tableaux,
CallableExpr(...)
respecte la portée du point où il est créé :
Exemple #2 Comparaison de portée de CallableExpr(...)
et des callables traditionnels
<?php
class Foo {
public function getPrivateMethod() {
return [$this, 'privateMethod'];
}
private function privateMethod() {
echo __METHOD__, "\n";
}
}
$foo = new Foo;
$privateMethod = $foo->getPrivateMethod();
$privateMethod();
// Fatal error: Call to private method Foo::privateMethod() from global scope
// This is because call is performed outside from Foo and visibility will be checked from this point.
class Foo1 {
public function getPrivateMethod() {
// Uses the scope where the callable is acquired.
return $this->privateMethod(...); // identical to Closure::fromCallable([$this, 'privateMethod']);
}
private function privateMethod() {
echo __METHOD__, "\n";
}
}
$foo1 = new Foo1;
$privateMethod = $foo1->getPrivateMethod();
$privateMethod(); // Foo1::privateMethod
?>
Note:
La création d'objets avec cette syntaxe (e.g
new Foo(...)
) n'est pas supportée, car la syntaxenew Foo()
n'est pas considérée comme un appel.
Note:
La syntaxe de callable de première classe ne peut pas être combinée avec l'opérateur nullsafe. Les deux cas suivants entraînent une erreur de compilation :
<?php
$obj?->method(...);
$obj?->prop->method(...);
?>