Php create function with callback
Callback-функции могут быть обозначены объявлением типа callable .
Некоторые функции, такие как call_user_func() или usort() , принимают определённые пользователем callback-функции в качестве параметра. Callback-функции могут быть как простыми функциями, так и методами объектов, включая статические методы классов.
Передача
В PHP функции передаются по имени в виде строки. Можно использовать любые встроенные, либо созданные пользователем функции, за исключением конструкций языка, таких как: array() , echo , empty() , eval() , exit() , isset() , list() , print или unset() .
Метод созданного объекта ( object ) передаётся как массив, содержащий объект по индексу 0 и имя метода по индексу 1. Доступ к закрытым и защищённым методам разрешён изнутри класса.
Статические методы класса также могут быть вызваны без создания экземпляра объекта класса путём передачи имени класса вместо объекта в элементе массива с индексом 0 или выполнения ‘ClassName::methodName’ .
Помимо обычных пользовательских функций, в качестве callback-функции можно передавать анонимные функции и стрелочные функции.
Замечание:
Начиная с PHP 8.1.0, у Callback-функций как объектов первого класса та же семантика, что и у этого метода.
Как правило, любой объект, реализующий __invoke(), также может быть передан в параметр callback.
Пример #1 Пример callback-функции
// Пример callback-функции
function my_callback_function () echo ‘Привет, мир!’ ;
>
// Пример callback-метода
class MyClass static function myCallbackMethod () echo ‘Привет, мир!’ ;
>
>
// Тип 1: Простой callback
call_user_func ( ‘my_callback_function’ );
// Тип 2: Вызов статического метода класса
call_user_func (array( ‘MyClass’ , ‘myCallbackMethod’ ));
// Тип 3: Вызов метода класса
$obj = new MyClass ();
call_user_func (array( $obj , ‘myCallbackMethod’ ));
// Тип 4: Вызов статического метода класса
call_user_func ( ‘MyClass::myCallbackMethod’ );
// Тип 5: Вызов относительного статического метода
class A public static function who () echo «A\n» ;
>
>
class B extends A public static function who () echo «B\n» ;
>
>
call_user_func (array( ‘B’ , ‘parent::who’ )); // A, устарело, начиная с PHP 8.2.0
// Тип 6: Объекты, реализующие __invoke, могут быть использованы как callback
class C public function __invoke ( $name ) echo ‘Привет ‘ , $name , «\n» ;
>
>
$c = new C ();
call_user_func ( $c , ‘PHP!’ );
?>
Пример #2 Пример callback-функции с использованием замыкания
// Наше замыкание
$double = function( $a ) return $a * 2 ;
>;
?php
// Диапазон чисел
$numbers = range ( 1 , 5 );
// Использование замыкания в качестве callback-функции
// для удвоения каждого элемента в нашем диапазоне
$new_numbers = array_map ( $double , $numbers );
print implode ( ‘ ‘ , $new_numbers );
?>
Результат выполнения данного примера:
Замечание:
Callback-функции, зарегистрированные такими функциями как call_user_func() и call_user_func_array() , не будут вызваны при наличии не пойманного исключения, брошенного в предыдущей callback-функции.
User Contributed Notes 19 notes
You can also use the $this variable to specify a callback:
public $property = ‘Hello World!’ ;
public function MyMethod ()
<
call_user_func (array( $this , ‘myCallbackMethod’ ));
>
public function MyCallbackMethod ()
<
echo $this -> property ;
>
Performance note: The callable type hint, like is_callable(), will trigger an autoload of the class if the value looks like a static method callback.
When specifying a call back in array notation (ie. array($this, «myfunc») ) the method can be private if called from inside the class, but if you call it from outside you’ll get a warning:
class mc <
public function go (array $arr ) <
array_walk ( $arr , array( $this , «walkIt» ));
>
private function walkIt ( $val ) <
echo $val . «
» ;
>
public function export () <
return array( $this , ‘walkIt’ );
>
>
$m = new mc ;
$m -> go ( $data ); // valid
array_walk ( $data , $m -> export ()); // will generate warning
?>
Output:
1
2
3
4
Warning: array_walk() expects parameter 2 to be a valid callback, cannot access private method mc::walkIt() in /in/tfh7f on line 22
A note on differences when calling callbacks as «variable functions» without the use of call_user_func() (e.g. » «):
?php>
— Using the name of a function as string has worked since at least 4.3.0
— Calling anonymous functions and invokable objects has worked since 5.3.0
— Using the array structure [$object, ‘method’] has worked since 5.4.0
Note, however, that the following are not supported when calling callbacks as variable functions, even though they are supported by call_user_func():
— Calling static class methods via strings such as ‘foo::doStuff’
— Calling parent method using the [$object, ‘parent::method’] array structure
All of these cases are correctly recognized as callbacks by the ‘callable’ type hint, however. Thus, the following code will produce an error «Fatal error: Call to undefined function foo::doStuff() in /tmp/code.php on line 4»:
class foo static function callIt (callable $callback ) $callback ();
>
static function doStuff () echo «Hello World!» ;
>
>
foo :: callIt ( ‘foo::doStuff’ );
?>
The code would work fine, if we replaced the ‘$callback()’ with ‘call_user_func($callback)’ or if we used the array [‘foo’, ‘doStuff’] as the callback instead.
You can use ‘self::methodName’ as a callable, but this is dangerous. Consider this example:
class Foo public static function doAwesomeThings () FunctionCaller :: callIt ( ‘self::someAwesomeMethod’ );
>
public static function someAwesomeMethod () // fantastic code goes here.
>
>
class FunctionCaller public static function callIt (callable $func ) call_user_func ( $func );
>
>
Foo :: doAwesomeThings ();
?>
This results in an error:
Warning: class ‘FunctionCaller’ does not have a method ‘someAwesomeMethod’.
For this reason you should always use the full class name:
FunctionCaller :: callIt ( ‘Foo::someAwesomeMethod’ );
?>
I believe this is because there is no way for FunctionCaller to know that the string ‘self’ at one point referred to to `Foo`.
> As of PHP 5.2.3, it is also possible to pass ‘ClassName::methodName’
You can also use ‘self::methodName’. This works in PHP 5.2.12 for me.
I needed a function that would determine the type of callable being passed, and, eventually,
normalized it to some extent. Here’s what I came up with:
/**
* The callable types and normalizations are given in the table below:
*
* Callable | Normalization | Type
* ———————————+———————————+—————
* function (. ) use (. ) <. >| function (. ) use (. ) <. >| ‘closure’
* $object | $object | ‘invocable’
* «function» | «function» | ‘function’
* «class::method» | [«class», «method»] | ‘static’
* [«class», «parent::method»] | [«parent of class», «method»] | ‘static’
* [«class», «self::method»] | [«class», «method»] | ‘static’
* [«class», «method»] | [«class», «method»] | ‘static’
* [$object, «parent::method»] | [$object, «parent::method»] | ‘object’
* [$object, «self::method»] | [$object, «method»] | ‘object’
* [$object, «method»] | [$object, «method»] | ‘object’
* ———————————+———————————+—————
* other callable | idem | ‘unknown’
* ———————————+———————————+—————
* not a callable | null | false
*
* If the «strict» parameter is set to true, additional checks are
* performed, in particular:
* — when a callable string of the form «class::method» or a callable array
* of the form [«class», «method»] is given, the method must be a static one,
* — when a callable array of the form [$object, «method»] is given, the
* method must be a non-static one.
*
*/
function callableType ( $callable , $strict = true , callable& $norm = null ) if (! is_callable ( $callable )) switch ( true ) case is_object ( $callable ):
$norm = $callable ;
return ‘Closure’ === get_class ( $callable ) ? ‘closure’ : ‘invocable’ ;
case is_string ( $callable ):
$m = null ;
if ( preg_match ( ‘~^(?[a-z_][a-z0-9_]*)::(?[a-z_][a-z0-9_]*)$~i’ , $callable , $m )) list( $left , $right ) = [ $m [ ‘class’ ], $m [ ‘method’ ]];
if (! $strict || (new \ ReflectionMethod ( $left , $right ))-> isStatic ()) $norm = [ $left , $right ];
return ‘static’ ;
>
> else $norm = $callable ;
return ‘function’ ;
>
break;
case is_array ( $callable ):
$m = null ;
if ( preg_match ( ‘~^(:?(?self|parent)::)?(?[a-z_][a-z0-9_]*)$~i’ , $callable [ 1 ], $m )) if ( is_string ( $callable [ 0 ])) if ( ‘parent’ === strtolower ( $m [ ‘reference’ ])) list( $left , $right ) = [ get_parent_class ( $callable [ 0 ]), $m [ ‘method’ ]];
> else list( $left , $right ) = [ $callable [ 0 ], $m [ ‘method’ ]];
>
if (! $strict || (new \ ReflectionMethod ( $left , $right ))-> isStatic ()) $norm = [ $left , $right ];
return ‘static’ ;
>
> else if ( ‘self’ === strtolower ( $m [ ‘reference’ ])) list( $left , $right ) = [ $callable [ 0 ], $m [ ‘method’ ]];
> else list( $left , $right ) = $callable ;
>
if (! $strict || !(new \ ReflectionMethod ( $left , $right ))-> isStatic ()) $norm = [ $left , $right ];
return ‘object’ ;
>
>
>
break;
>
$norm = $callable ;
return ‘unknown’ ;
>
$norm = null ;
return false ;
>
?>
Hope someone else finds it useful.
PHP Callback Functions
A callback function (often referred to as just «callback») is a function which is passed as an argument into another function.
Any existing function can be used as a callback function. To use a function as a callback function, pass a string containing the name of the function as the argument of another function:
Example
Pass a callback to PHP’s array_map() function to calculate the length of every string in an array:
$strings = [«apple», «orange», «banana», «coconut»];
$lengths = array_map(«my_callback», $strings);
print_r($lengths);
?>
Starting with version 7, PHP can pass anonymous functions as callback functions:
Example
Use an anonymous function as a callback for PHP’s array_map() function:
$strings = [«apple», «orange», «banana», «coconut»];
$lengths = array_map( function($item) < return strlen($item); >, $strings);
print_r($lengths);
?>?php
Callbacks in User Defined Functions
User-defined functions and methods can also take callback functions as arguments. To use callback functions inside a user-defined function or method, call it by adding parentheses to the variable and pass arguments as with normal functions:
Example
Run a callback from a user-defined function:
function ask($str) return $str . «? «;
>
function printFormatted($str, $format) // Calling the $format callback function
echo $format($str);
>
// Pass «exclaim» and «ask» as callback functions to printFormatted()
printFormatted(«Hello world», «exclaim»);
printFormatted(«Hello world», «ask»);
?>
Функции обратного вызова в PHP
Функция обратного вызова (часто называемая просто «callback») — это функция, которая передается в качестве аргумента другой функции.
Функции обратного вызова
Любая существующая функция может использоваться как функция обратного вызова. Чтобы использовать функцию в качестве функции обратного вызова, передайте строку, содержащую имя функции, в качестве аргумента другой функции.
В следующем примере, чтобы вычислить длину каждой строки (в нашем случае названия брендов смартфонов) в массиве, мы передаём обратный вызов функции array_map() :
Пример
$strings = ["Apple", "Asus", "Huawei", "Lenovo"]; $lengths = array_map("my_callback", $strings); print_r($lengths); ?>
Начиная с седьмой версии PHP может передавать анонимные функции как функции обратного вызова. Напомним, что анонимные функции, также известные как замыкания (closures), позволяют создавать функции, не имеющие определенных имен.
В следующем примере мы используем анонимную функцию в качестве «callback» для функции array_map() :
Пример
Обратные вызовы в пользовательских функциях
Пользовательские функции и методы в PHP также могут принимать функции обратного вызова bkb «callback» в качестве параметров.
Для того, чтобы внутри пользовательской функции или метода, использовать функцию обратного вызова её нужно вызвать, добавив круглые скобки к переменной и передавая аргументы, как с обычными функциями:
Пример
function ask($str) < return $str . "? "; >function printFormatted($str, $format) < /* Вызов функции обратного вызова $format */ echo $format($str); >/* Передадим "exclaim" и "ask" в качестве функций обратного вызова printFormatted() */ printFormatted("Hello world", "exclaim"); printFormatted("Hello world", "ask"); ?>