## Syntaxe callable de première classe

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(...);  // objet invocable
    $f3 = $obj->method(...);
    $f4 = $obj->$methodStr(...);
    $f5 = Foo::staticmethod(...);
    $f6 = $classStr::$staticmethodStr(...);
    // callable traditionnel utilisant une chaîne, un tableau
    $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();
    // Erreur fatale : Call to private method Foo::privateMethod() from global scope
    // Ceci est dû au fait que l'appel est effectué en dehors de Foo et la visibilité sera vérifiée depuis ce point.

    <?php
    class Foo1 {
        public function getPrivateMethod() {
            // Utilise la portée où le callable est acquis.
            return $this->privateMethod(...); // identique à 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 syntaxe `new 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(...);

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