Callback-Funktionen als Objekte erster Klasse
Callback-Funktionen als Objekte erster Klasse wurde mit PHP 8.1.0 eingeführt, um anonyme Funktionen aus Callback-Funktionen zu erstellen. Sie ersetzt die bestehende Callback-Syntax, die Strings und Arrays verwendet. Der Vorteil dieser Syntax ist, dass sie für die statische Analyse zugänglich ist und den Gültigkeitsbereich an der Stelle verwendet, an der die Callback-Funktion aufgerufen wird.
Die CallableExpr(...)
-Syntax wird verwendet, um ein
Closure-Objekt aus einer Callback-Funktion zu
erzeugen. CallableExpr
akzeptiert jeden Ausdruck, der in der
PHP-Grammatik direkt aufgerufen werden kann:
Beispiel #1 Einfaches Beispiel für eine Callback-Funktion als Objekt erster Klasse
<?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(...); // Callback-Objekt
$f3 = $obj->method(...);
$f4 = $obj->$methodStr(...);
$f5 = Foo::staticmethod(...);
$f6 = $classStr::$staticmethodStr(...);
// traditionelle Callback-Funktion mit String, Array
$f7 = 'strlen'(...);
$f8 = [$obj, 'method'](...);
$f9 = [Foo::class, 'staticmethod'](...);
?>
Hinweis:
Das
...
ist keine Auslassung, sondern Teil der Syntax.
CallableExpr(...)
hat die gleiche Semantik wie
Closure::fromCallable(). Das heißt, im Gegensatz zu
Callback-Funktionen, die Strings und Arrays verwenden, wird bei
CallableExpr(...)
der Geltungsbereich an dem Punkt
berücksichtigt, an dem er erstellt wird:
Beispiel #2 Vergleich des Anwendungsbereichs von CallableExpr(...)
und traditionellen Callback-Funktionen
<?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
// Dies liegt daran, dass der Aufruf außerhalb von Foo erfolgt und die Sichtbarkeit ab diesem Punkt geprüft wird.
class Foo1 {
public function getPrivateMethod() {
// Verwendet den Bereich, in dem die Callback-Funktion aufgerufen wird.
return $this->privateMethod(...); // identisch mit Closure::fromCallable([$this, 'privateMethod']);
}
private function privateMethod() {
echo __METHOD__, "\n";
}
}
$foo1 = new Foo1;
$privateMethod = $foo1->getPrivateMethod();
$privateMethod(); // Foo1::privateMethod
?>
Hinweis:
Die Erzeugung von Objekten mit dieser Syntax (z. B.
new Foo(...)
) wird nicht unterstützt, da dienew Foo()
-Syntax nicht als Aufruf betrachtet wird.
Hinweis:
Callback-Funktionen als Objekte erster Klasse können nicht mit dem Nullsafe-Operator kombiniert werden. Beides führt zu einem Fehler bei der Kompilierung:
<?php
$obj?->method(...);
$obj?->prop->method(...);
?>