There's a major gotcha with this syntax that may not be apparent until you use this syntax and find you're getting "Cannot rebind scope of closure created from method" exceptions in some random library code.
As the documentation indicates, the first-class callable uses the scope at the point where the callable is acquired. This is fine as long as nothing in your code will attempt to bind the callable with the \Closure::bindTo method.
I found this the hard way by changing callables going to Laravel's Macroable functionality from the array style to the first-class callable style. The Macroable functionality \Closure::bindTo calls on the callable.
AFAIK, the only workaround is to use the uglier array syntax.Синтакса за повикување од прва класа
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
Синтакса за повикување од прва класа
Референца за `functions.first_class_callable_syntax.php` со подобрена типографија и навигација.
Синтакса за повикување од прва класа
The first class callable syntax is introduced as of PHP 8.1.0, as a way of creating анонимни функции from callableСинтаксата за повикливи од прва класа е воведена од PHP 8.1.0, како начин за креирање
CallableExpr(...) . Таа ги надминува постоечките синтакси за повикливи што користат низи и низи. Предноста на оваа синтакса е што е достапна за статичка анализа и ја користи опсегот во точката каде што се стекнува повикливиот. Затворање синтаксата се користи за креирање на CallableExpr објект од повикливиот.
прифаќа кој било израз што може директно да се повика во PHP граматиката:
<?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'](...);
?>Забелешка:
На
...Пример #1 Едноставна синтакса за повикливи од прва класа
CallableExpr(...) е дел од синтаксата, а не пропуст. има исти семантики какоClosure::fromCallable() CallableExpr(...) . Тоа е, за разлика од повикливите што користат низи и низи,
го почитува опсегот во точката каде што е создаден: CallableExpr(...) Пример #2 Споредба на опсегот на
<?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
?>Забелешка:
и традиционални повикливи
new Foo(...)Креирање објект со оваа синтакса (на пр.new Foo()) не е поддржано, бидејќи
Забелешка:
синтаксата не се смета за повик. nullsafe операторСинтаксата за повикливи од прва класа не може да се комбинира со
<?php
$obj?->method(...);
$obj?->prop->method(...);
?>
Белешки од корисници 2 забелешки
Also note that closures are not serializable. So if you are storing a reference to a callback in a variable that will be serialized for caching or any other purpose, do not switch to this syntax or your serialization will break.