Як назвати закриття, яке є змінною класу?


78
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()

Отже, який правильний синтаксис для досягнення змінних класу?

Відповіді:


197

У PHP методи та властивості знаходяться в окремому просторі імен (ви можете мати метод і властивість з однаковим іменем), і чи ви отримуєте доступ до властивості чи методу, залежить від синтаксису, який ви використовуєте для цього.

$expr->something()є викликом методу, тому PHP буде шукати somethingв списку методів класу.

$expr->somethingє somethingвибором властивості , тому PHP буде шукати у списку властивостей класу.

$myInstance->lambda();аналізується як виклик методу, тому PHP шукає метод, названий lambdaу вашому класі, але такого методу немає (звідси помилка виклику невизначеного методу ).

Отже, ви повинні використовувати синтаксис властивості fetch для отримання лямбда-сигналу, а потім викликати його.

  • Оскільки PHP 7.0, ви можете зробити це за допомогою ($obj->lambda)():

    ($obj->lambda)();
    

    У дужках переконайтеся, що PHP аналізує ($obj->lambda)при виборі властивості з іменем лямбда . Потім ()викликає результат отримання властивості.

  • або ви можете зробити це за допомогою ->lambda->__invoke():

    $myInstance = new MyClass();
    $myInstance->lambda->__invoke();
    

    __invokeє одним із магічних методів PHP . Коли об’єкт реалізує цей метод, він стає викликаним: його можна викликати за допомогою $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();
    

Приємно, хоча було б непогано бачити __invoke/()проти call_user_funcзаміток.

1
ви можете використовувати риси майже для всього, це не клас, просто
неширокий

2

Ви також можете викликати свою лямбда-функцію, не змінюючи щось у своєму класі, використовуючи ReflectionFunction.

$myInstance = new MyClass();
$lambda = new ReflectionFunction($myInstance->lambda);
$lambda->invoke();

або якщо вам доведеться передати аргументи тоді

$args = array('arg'=>'value');
$lambda->invokeArgs($args);

1
Це не найкоротший і не найефективніший спосіб цього зробити.
амфетамахін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.