class MyClass { var $lambda; function __construct() { $this->lambda = function() {echo 'hello world';}; // no errors here, so I assume that this is legal } } $myInstance = new MyClass(); $myInstance->lambda(); //Fatal error: Call to undefined method MyClass::lambda()
Итак, каков правильный синтаксис для достижения переменных класса?
В PHP методы и свойства находятся в отдельном пространстве имен (у вас может быть метод и свойство с тем же именем), и независимо от того, используете ли вы свойство или метод, зависит от синтаксиса, который вы используете для этого.
$expr->something()
– вызов метода, поэтому PHP будет искать something
в списке методов класса.
$expr->something
есть свойство fetch, поэтому PHP будет искать something
в списке свойств класса.
$myInstance->lambda();
анализируется как вызов метода, поэтому PHP ищет метод с именем lambda
в вашем классе, но такого метода нет (следовательно, вызов для неопределенной ошибки метода ).
Поэтому вам нужно использовать синтаксис свойства fetch для извлечения лямбда, а затем вызвать его.
Начиная с PHP 7.0, вы можете сделать это с помощью ($obj->lambda)()
:
($obj->lambda)();
В скобках убедитесь, что PHP анализирует ($obj->lambda)
как свойство свойства lambda . Затем ()
вызывает результат получения свойства.
или вы можете сделать это с помощью ->lambda->__invoke()
:
$myInstance = new MyClass(); $myInstance->lambda->__invoke();
__invoke
является одним из магических методов PHP . Когда объект реализует этот метод, он становится invokable: его можно вызвать с помощью синтаксиса $var()
. Анонимными функциями являются экземпляры Closure
, которые реализуют __invoke
.
Или назначьте его локальной переменной:
$lambda = $myInstance->lambda; $lambda();
Или вызовите его с помощью call_user_func:
call_user_func($myInstance->lambda);
call_user_func
может вызывать любые callable
, включая анонимные функции.
В качестве альтернативы, если это общий шаблон в коде, вы можете настроить метод __call
для переадресации вызовов на ваш лямбда:
class MyClass { private $lambda; public function __construct() { $this->lambda = function() { echo "Hello world!\n"; }; } public function __call($name, $args) { return call_user_func_array($this->$name, $args); } }
Теперь это работает:
$myInstance = new MyClass(); $myInstance->lambda();
Начиная с PHP 5.4 вы можете даже сделать это в признаке:
trait LambdasAsMethods { public function __call($name, $args) { return call_user_func_array($this->$name, $args); } } class MyClass { use LambdasAsMethods; private $lambda; public function __construct() { $this->lambda = function() { echo "Hello World!\n"; }; } } $myInstance = new MyClass(); $myInstance->lambda();
Вы также можете вызвать свою лямбда-функцию без каких-либо изменений в своем классе, используя ReflectionFunction.
$myInstance = new MyClass(); $lambda = new ReflectionFunction($myInstance->lambda); $lambda->invoke();
или если вам нужно передать аргументы, то
$args = array('arg'=>'value'); $lambda->invokeArgs($args);