## 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 die `new 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(...);
>     ?>

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open