Callback-функции как объекты первого класса

Callback-функции как объекты первого класса представлены в PHP 8.1.0 как способ создания анонимных функций из callback-функций. Синтаксис заменяет существующий синтаксис вызова с использованием строк и массивов. Преимущество синтаксиса заключается в том, что он доступен для статического анализа и использует область видимости в точке, где получена callback-функция.

Синтаксис CallableExpr(...) используется для создания объекта Closure из callback-функции. CallableExpr принимает любое выражение, которое может быть вызвано напрямую в грамматике PHP:

Пример #1 Простой пример callback-функции как объекты первого класса

<?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(...);  // вызываемый объект
$f3 $obj->method(...);
$f4 $obj->$methodStr(...);
$f5 Foo::staticmethod(...);
$f6 $classStr::$staticmethodStr(...);
// традиционная callback-функция с использованием строки, массива
$f7 'strlen'(...);
$f8 = [$obj'method'](...);
$f9 = [Foo::class, 'staticmethod'](...);
?>

Замечание:

... является частью синтаксиса, а не пропуском.

У CallableExpr(...) та же семантика, что и у Closure::fromCallable(). То есть, в отличие от callback-функции с использованием строк и массивов, CallableExpr(...) учитывает область видимости в точке, где она создаётся:

Пример #2 Сравнение области действия CallableExpr(...) и традиционной callback-функции

<?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
// Это потому, что вызов выполняется вне Foo, и с этого момента будет проверяться видимость.
class Foo1 {
    public function 
getPrivateMethod() {
        
// Использует область, в которой получена callback-функция.
        
return $this->privateMethod(...); // идентично Closure::fromCallable([$this, 'privateMethod']);
    
}
    private function 
privateMethod() {
        echo 
__METHOD__"\n";
    }
}
$foo1 = new Foo1;
$privateMethod $foo1->getPrivateMethod();
$privateMethod();  // Foo1::privateMethod
?>

Замечание:

Создание объекта с помощью этого синтаксиса (например, new Foo(...)) не поддерживается, поскольку синтаксис new Foo() не считается callback-функцией.

Замечание:

Callback-функции как объекты первого класса нельзя комбинировать с оператором Nullsafe. Оба следующих результата приводят к ошибке времени компиляции:

<?php
$obj
?->method(...);
$obj?->prop->method(...);
?>

add a note add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top