Я хотел бы иметь возможность вызывать замыкание, которое я назначаю свойству объекта напрямую, без переназначения замыкания переменной и последующего ее вызова. Это возможно?
Код ниже не работает и вызывает Fatal error: Call to undefined method stdClass::callback()
.
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback();
php
object
properties
closures
Кендалл Хопкинс
источник
источник
Ответы:
Начиная с PHP7, вы можете делать
или используйте Closure :: call () , хотя это не работает с
StdClass
.До PHP7 вам нужно было реализовать волшебный
__call
метод для перехвата вызова и вызова обратного вызова (что,StdClass
конечно, невозможно , потому что вы не можете добавить__call
метод)Обратите внимание, что вы не можете делать
в
__call
теле, потому что это вызовет__call
бесконечный цикл.источник
Вы можете сделать это, вызвав __invoke при закрытии, поскольку это магический метод, который объекты используют для поведения функций:
Конечно, это не сработает, если обратный вызов представляет собой массив или строку (которые также могут быть действительными обратными вызовами в PHP) - только для замыканий и других объектов с поведением __invoke.
источник
call_user_func($obj->callback)
не так уж и плохо.call_user_func
работает и со струнами, и это не всегда удобно$obj->callback->__invoke();
когда этого можно было ожидать$obj->callback()
. Это просто вопрос последовательности.$obj->callback instanceof \Closure
.Начиная с PHP 7, вы можете делать следующее:
источник
Начиная с PHP 7, замыкание можно вызвать с помощью
call()
метода:Поскольку PHP 7 также может выполнять операции с произвольными
(...)
выражениями (как объяснил Корикулум ):Другие распространенные подходы PHP 5 :
используя магический метод
__invoke()
(как объяснил Бриллиан )используя
call_user_func()
функциюиспользование промежуточной переменной в выражении
У каждого способа есть свои плюсы и минусы, но наиболее радикальным и окончательным решением остается то, что предлагает Гордон .
источник
Вроде можно использовать
call_user_func()
.не элегантно, хотя .... То, что говорит @Gordon, вероятно, единственный выход.
источник
Хорошо, если очень настаиваешь. Другой обходной путь:
Но это не самый лучший синтаксис.
Однако, PHP парсер всегда лечит
T_OBJECT_OPERATOR
,IDENTIFIER
, в(
качестве вызова метода. Кажется, не существует обходного пути для->
обхода таблицы методов и доступа вместо этого к атрибутам.источник
Я знаю, что это устарело, но я думаю, что Traits прекрасно справляется с этой проблемой, если вы используете PHP 5.4+.
Сначала создайте трейт, который делает свойства вызываемыми:
Затем вы можете использовать эту черту в своих классах:
Теперь вы можете определять свойства через анонимные функции и вызывать их напрямую:
источник
ну, следует подчеркнуть, что сохранение замыкания в переменной и вызов переменной на самом деле (странно) быстрее, в зависимости от количества вызовов, это становится довольно много, с xdebug (очень точное измерение), мы говорим о 1,5 (коэффициент, используя переменную вместо прямого вызова __invoke. Поэтому вместо этого просто сохраните закрытие в переменной и вызовите его.
источник
Вот еще одна альтернатива, основанная на принятом ответе, но напрямую расширяющая stdClass:
Пример использования:
Вам, вероятно, лучше использовать
call_user_func
или__invoke
хотя.источник
Обновлено:
PHP> = 7:
PHP> = 5.4:
источник
Call to undefined method AnyObject::callback()
(Класс AnyObject, конечно, существует.)Если вы используете PHP 5.4 или выше, вы можете привязать вызываемый объект к области видимости вашего объекта, чтобы вызвать настраиваемое поведение. Так, например, если у вас будет следующая настройка ...
И вы оперировали таким классом ..
Вы можете запустить свою собственную логику, как если бы вы работали в рамках своего объекта.
источник
Замечу, что это работает в PHP5.5.
Позволяет создать коллекцию замыканий псевдо-объекта.
источник