Как обратные вызовы написаны на PHP?
В руководстве используются термины «обратный вызов» и «вызываемый» взаимозаменяемо, однако «обратный вызов» традиционно относится к значению строки или массива, которое действует как указатель функции , ссылаясь на функцию или метод класса для будущего вызова. Это позволило некоторым элементам функционального программирования с 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
поддерживают все вышеперечисленное.
См .: http://php.net/manual/en/language.types.callable.php
Примечания / Предостережения:
['Vendor\Package\Foo', 'method']
call_user_func
не поддерживает передачу не-объектов по ссылке, поэтому вы можете использовать call_user_func_array
или, в более поздних версиях PHP, сохранить обратный вызов в var и использовать прямой синтаксис: $cb()
; __invoke()
(включая анонимные функции) относятся к категории «вызываемые» и могут использоваться одинаково, но я лично не связываю их с устаревшим термином «обратный вызов». create_function()
создает глобальную функцию и возвращает ее имя. Это оболочка для eval()
и вместо нее следует использовать анонимные функции. С помощью 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');
Дисплеи: данные: это мои данные
Одним из замечательных трюков, которые я недавно нашел, является использование PHP create_function()
для создания анонимной / лямбда-функции для одноразового использования. Это полезно для функций PHP, таких как array_map()
, preg_replace_callback()
или usort()
которые используют обратные вызовы для пользовательской обработки. Он выглядит очень похож на eval()
под обложками, но это по-прежнему хороший функциональный способ использования PHP.
хорошо … с 5.3 на горизонте, все будет лучше, потому что с 5.3 мы получим замыкания и с ними анонимные функции
Вы захотите проверить, действительно ли ваш вызов действителен. Например, в случае конкретной функции вы хотите проверить и посмотреть, существует ли функция:
function doIt($callback) { if(function_exists($callback)) { $callback(); } else { // some error handling } }
create_function
не работал для меня внутри класса. Мне пришлось использовать call_user_func
.
<?php class Dispatcher { //Added explicit callback declaration. var $callback; public function Dispatcher( $callback ){ $this->callback = $callback; } public function asynchronous_method(){ //do asynch stuff, like fwrite...then, fire callback. if ( isset( $this->callback ) ) { if (function_exists( $this->callback )) call_user_func( $this->callback, "File done!" ); } } }
Затем, чтобы использовать:
<?php include_once('Dispatcher.php'); $d = new Dispatcher( 'do_callback' ); $d->asynchronous_method(); function do_callback( $data ){ print 'Data is: ' . $data . "\n"; } ?>
[Edit] Добавлена отсутствующая скобка. Кроме того, добавлено объявление обратного вызова, я предпочитаю его таким образом.
Я сжимаю каждый раз, когда я использую create_function()
в php.
Параметры – это кома-разделенная строка, целое тело функции в строке … Арг … Я думаю, что они не могли бы сделать ее более уродливой, даже если бы они попытались.
К сожалению, это единственный выбор, когда создание названной функции не стоит проблем.
Для тех, кто не заботится о нарушении совместимости с PHP < 5.4
, я бы предложил использовать тип намека, чтобы сделать более чистую реализацию.
function call_with_hello_and_append_world( callable $callback ) { // No need to check $closure because of the type hint return $callback( "hello" )."world"; } function append_space( $string ) { return $string." "; } $output1 = call_with_hello_and_append_world( function( $string ) { return $string." "; } ); var_dump( $output1 ); // string(11) "hello world" $output2 = call_with_hello_and_append_world( "append_space" ); var_dump( $output2 ); // string(11) "hello world" $old_lambda = create_function( '$string', 'return $string." ";' ); $output3 = call_with_hello_and_append_world( $old_lambda ); var_dump( $output3 ); // string(11) "hello world"