Собираюсь связать другой вопрос с этим, потому что я пытался назвать закрытие.
akinuri
Ответы:
173
В руководстве термины «обратный вызов» и «вызываемый» используются взаимозаменяемо, однако «обратный вызов» традиционно относится к значению строки или массива, которое действует как указатель на функцию , ссылаясь на метод функции или класса для последующего вызова. Это позволило некоторые элементы функционального программирования начиная с PHP 4. Ароматы:
$cb1 ='someGlobalFunction';
$cb2 =['ClassName','someStaticMethod'];
$cb3 =[$object,'somePublicMethod'];// this syntax is callable since PHP 5.2.3 but a string containing it// cannot be called directly
$cb2 ='ClassName::someStaticMethod';
$cb2();// fatal error// legacy syntax for PHP 4
$cb3 = array(&$object,'somePublicMethod');
Это безопасный способ использовать вызываемые значения в целом:
if(is_callable($cb2)){// Autoloading will be invoked to load the class "ClassName" if it's not// yet defined, and PHP will check that the class has a method// "someStaticMethod". Note that is_callable() will NOT verify that the// method can safely be executed in static context.
$returnValue = call_user_func($cb2, $arg1, $arg2);}
Современные версии PHP позволяют напрямую вызывать первые три формата, указанные выше $cb(). call_user_funcи call_user_func_arrayподдерживать все вышеперечисленное.
Если функция / класс находится в пространстве имен, строка должна содержать полное имя. Например['Vendor\Package\Foo', 'method']
call_user_funcне поддерживает прохождение не-объектов с помощью ссылки, так что вы можете использовать call_user_func_arrayили, в более поздних версиях PHP, сохранить обратный вызов в вар и использовать прямой синтаксис: $cb();
Объекты с __invoke()методом (включая анонимные функции) подпадают под категорию «вызываемые» и могут использоваться таким же образом, но я лично не связываю их с устаревшим термином «обратный вызов».
Наследие create_function()создает глобальную функцию и возвращает ее имя. Это обертка для eval()и вместо нее должны использоваться анонимные функции.
Действительно, использование функции является правильным способом сделать это. Используя переменную и затем просто вызывая ее, как предлагается в принятом ответе, это круто, это уродливо и плохо масштабируется с кодом.
icco
4
Изменен принятый ответ. Согласен с комментариями, это отличный ответ.
Ник Stinemates
Читателям из программирования на Python было бы полезно указать в ответе, что 'someGlobalFunction'это определенная функция.
TMOTTM
1
Начиная с PHP 5.3, есть замыкания, см . Ответ Барта ван Хейкелома . Это намного проще и "стандартнее", чем весь этот старый беспорядок.
действительно хорошая
Да, я упоминаю анонимные функции в своем ответе, но ОП попросил «обратный вызов» (в 2008 году), и эти обратные вызовы более старого стиля все еще очень широко используются в тоннах кодовых баз PHP.
Стив Клэй,
74
С PHP 5.3 вы можете сделать это:
function doIt($callback){ $callback();}
doIt(function(){// this will be done});
Наконец-то хороший способ сделать это. Отличное дополнение к PHP, потому что обратные вызовы потрясающие.
// This function uses a callback function. function doIt($callback){
$data ="this is my data";
$callback($data);}// This is a sample callback function for doIt(). function myCallback($data){print'Data is: '. $data ."\n";}// Call doIt() and pass our sample callback function's name.
doIt('myCallback');
Есть несколько других способов сделать это, как показано выше. Я действительно думал так же.
Ник Stinemates
3
@ Ник Реталлак, я не понимаю, что в этом такого ужасного. Для известных мне языков, таких как JavaScript и C #, все они могут структурировать свою функцию обратного вызова таким образом. Исходя из JavaScirpt и C #, я действительно не привык к call_user_func (). Это заставляет меня чувствовать, что я должен приспособиться к PHP, а не наоборот.
Антоний
4
@ Антония Я возражал против того факта, что строки на этом языке являются указателями на функции. Я опубликовал этот комментарий три года назад, так что к настоящему времени я довольно привык к нему, но я думаю, что PHP - единственный из известных мне языков (кроме сценариев оболочки), где это так.
Ник Реталлак
1
@ Антония Я предпочитаю использовать тот же синтаксис, который я использую в JavaScript. Поэтому я даже не понимаю, почему люди хотят использовать call_user_func()Когда у них есть синтаксис, который позволяет им динамически вызывать функции и делать обратные вызовы. Я согласен с тобой!
botenvouwer
9
Недавно я обнаружил один изящный прием - использовать PHP create_function()для создания анонимной / лямбда-функции для одноразового использования. Это полезно для PHP функций , таких как array_map(), preg_replace_callback(), или , usort()что использование обратных вызовов для таможенного оформления. Он выглядит почти так же, как и eval()под одеялом, но это все еще хороший способ использовать PHP в функциональном стиле.
К сожалению, сборщик мусора не очень хорошо работает с этой конструкцией, приводящей к потенциальным утечкам памяти. Если вам не хватает производительности, избегайте create_function ().
fuxia
1
Уч. Спасибо за хедз-ап.
yukondude
Не могли бы вы обновить ответ с версией PHP 7.4 (функции стрелок) и добавить предупреждение об устаревших create_function()?
Дхарман
7
хорошо ... с 5.3 на горизонте все будет лучше, потому что с 5.3 мы получим замыкания и с ними анонимные функции
Что если обратный вызов - это не функция, а массив, содержащий объект и метод?
d -_- b
3
точнееis_callable( $callback )
Roko C. Buljan
1
Оба являются хорошими предложениями - необходимо будет проверить собственную реализацию того, как вы выполняете обратный вызов. Я надеялся предостеречь от вызова чего-то несуществующего, что привело к фатальному исходу. Я сделал ответ более общим
SeanDowney
5
create_functionне работал для меня в классе. Я должен был использовать call_user_func.
Разве класс Dispatcher не требует атрибута для $ this-> callback = $ callback для работы?
Джеймс П.
@james Poulson: PHP динамический язык, поэтому он работает. Но мне было лень. Я обычно объявляю свойства, облегчает жизнь всем. Ваш вопрос заставил меня снова взглянуть на этот код и определить синтаксическую ошибку, ты. Спасибо
Голиатоне
Я не знал, что это возможно. Спасибо за ответ :) .
Джеймс П.
Не безопаснее ли объявить функцию do_callback перед созданием объекта Dispatcher и вызовом асинхронного метода?
ejectamenta
3
Я съеживаюсь каждый раз, когда использую create_function()в php.
Параметры - это строка, разделенная запятой, все тело функции в строке ... Аааа ... Я думаю, что они не могли бы сделать это еще хуже, даже если бы попытались.
К сожалению, это единственный выбор, когда создание именованной функции не стоит хлопот.
Ответы:
В руководстве термины «обратный вызов» и «вызываемый» используются взаимозаменяемо, однако «обратный вызов» традиционно относится к значению строки или массива, которое действует как указатель на функцию , ссылаясь на метод функции или класса для последующего вызова. Это позволило некоторые элементы функционального программирования начиная с PHP 4. Ароматы:
Это безопасный способ использовать вызываемые значения в целом:
Современные версии PHP позволяют напрямую вызывать первые три формата, указанные выше
$cb()
.call_user_func
иcall_user_func_array
поддерживать все вышеперечисленное.Смотрите: http://php.net/manual/en/language.types.callable.php
Примечания / Предостережения:
['Vendor\Package\Foo', 'method']
call_user_func
не поддерживает прохождение не-объектов с помощью ссылки, так что вы можете использоватьcall_user_func_array
или, в более поздних версиях PHP, сохранить обратный вызов в вар и использовать прямой синтаксис:$cb()
;__invoke()
методом (включая анонимные функции) подпадают под категорию «вызываемые» и могут использоваться таким же образом, но я лично не связываю их с устаревшим термином «обратный вызов».create_function()
создает глобальную функцию и возвращает ее имя. Это обертка дляeval()
и вместо нее должны использоваться анонимные функции.источник
'someGlobalFunction'
это определенная функция.С PHP 5.3 вы можете сделать это:
Наконец-то хороший способ сделать это. Отличное дополнение к PHP, потому что обратные вызовы потрясающие.
источник
Реализация обратного вызова делается так
Отображает: Данные есть: это мои данные
источник
call_user_func()
Когда у них есть синтаксис, который позволяет им динамически вызывать функции и делать обратные вызовы. Я согласен с тобой!Недавно я обнаружил один изящный прием - использовать PHP
create_function()
для создания анонимной / лямбда-функции для одноразового использования. Это полезно для PHP функций , таких какarray_map()
,preg_replace_callback()
, или ,usort()
что использование обратных вызовов для таможенного оформления. Он выглядит почти так же, как иeval()
под одеялом, но это все еще хороший способ использовать PHP в функциональном стиле.источник
create_function()
?хорошо ... с 5.3 на горизонте все будет лучше, потому что с 5.3 мы получим замыкания и с ними анонимные функции
http://wiki.php.net/rfc/closures
источник
Вы хотите проверить, что ваш звонок действителен. Например, в случае конкретной функции вы захотите проверить и посмотреть, существует ли функция:
источник
is_callable( $callback )
create_function
не работал для меня в классе. Я должен был использоватьcall_user_func
.Затем использовать:
[Править] Добавлена пропущенная скобка. Кроме того, добавил объявление обратного вызова, я предпочитаю это таким образом.
источник
Я съеживаюсь каждый раз, когда использую
create_function()
в php.Параметры - это строка, разделенная запятой, все тело функции в строке ... Аааа ... Я думаю, что они не могли бы сделать это еще хуже, даже если бы попытались.
К сожалению, это единственный выбор, когда создание именованной функции не стоит хлопот.
источник
create_function()
сейчас устарела и не должна использоваться.Для тех, кто не заботится о нарушении совместимости с PHP
< 5.4
, я бы предложил использовать подсказки типов для более чистой реализации.источник
create_function()
устарело с версии PHP 7.2.0. Полагаться на эту функцию крайне не рекомендуется.