## 回调函数 先看一下C语言里的回调函数:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 其他语言里的回调函数的概念与之相似,只不过各种语言里回调函数的实现机制不一样,通俗的来说,回调函数是一个我们定义的函数,但是不是我们直接来调用,而是通过另一个函数来调用,这个函数通过接收回调函数的名字和参数来实现对它的调用。 > 说明:回调函数就是调用函数的时候将另外一个函数的名称当作参数传递进去,并且在函数体中进行调用 案例 01 ```php function playing() { echo "is playing <br/>"; } function sleeping() { echo "is sleeping <br/>"; } function callback_test($fun_name) { $fun_name(); } callback_test('playing'); // is playing callback_test('sleeping'); // is sleeping ``` 案例 02 回调传入参数 ```php function play($param) { echo $param . " is playing <br/>"; } function sleeps($param) { echo $param . " is sleeping <br/>"; } function callback_param($fun_name, $param) { echo "现在调用的函数是... <br/>"; $fun_name($param); // playing() } callback_param('play', 'Tinywan'); ``` 案例 03 2个回调传入参数,做一个加减运算 ```php function add($x, $y) { return $x + $y; } function reduce($x, $y) { return $x - $y; } function math_param($fun_name, $x, $y) { return $fun_name($x, $y); } echo math_param('add', 10, 20); ``` >[info] 案例 04 `array_map` 函数 为数组的每个元素应用回调函数 语法: ``` array array_map ( callable $callback , array $array1 [, array $... ] ) ``` * 普通案例 ```php // 计算一个数的阶乘,eg: 2 阶乘 = 2 * 2 *2 function cube($n) { return ($n * $n * $n); } $tmp_arr = [1, 2, 3, 4]; $res = array_map('cube', $tmp_arr); print_r($res); // 打印结果 ( [0] => 1 [1] => 8 [2] => 27 [3] => 64 ) ``` * 通过匿名函数实现 ```php $tmp_arr2 = [2, 4, 6, 8]; $res2 = array_map(function ($n) { return ($n * 2); }, $tmp_arr2); print_r($res2); // 输出结果 Array ( [0] => 4 [1] => 8 [2] => 12 [3] => 16 ) ``` * 使用单个参数 ```php function findName($val){ if($val == 'Tinywan') { return 'ShaoBo Wan'; } return $val; } $nameArr = ['Ngix','Oxd','Tinywan']; $res = array_map('findName',$nameArr); print_r($res); // 输出结果 Array ( [0] => Ngix [1] => Oxd [2] => ShaoBo Wan ) ``` * 使用多个参数 ```php function funSame($v1,$v2){ if($v1 == $v2) { return 'same'; } return 'different'; } $arr01 = ['Ngix','Oxd','Tinywan']; $arr02 = ['Tiny','Tinaiai','Tinywan']; $res1 = array_map('funSame',$arr01,$arr02); print_r($res1); // 输出结果 Array ( [0] => different [1] => different [2] => same ) ``` * 当自定义函数名设置为 `null` 时 ```php $arr01 = ['Ngix','Oxd','Tinywan']; $arr02 = ['Tiny','Tinaiai','Tinywan']; $res2 = array_map(null,$arr01,$arr02); print_r($res2); // 输出结果 Array ( [0] => Array ( [0] => Ngix [1] => Tiny ) [1] => Array ( [0] => Oxd [1] => Tinaiai ) [2] => Array ( [0] => Tinywan [1] => Tinywan ) ) ``` > 可以看出回调函数设置为null的情况下,是把两个数组合并到一起,组装成一个新数组 >[info] 案例 05 `array_walk `函数 array_walk() 函数对数组中的每个元素应用回调函数。如果成功则返回 TRUE,否则返回 FALSE。 典型情况下 function 接受两个参数。array 参数的值作为第一个,键名作为第二个。如果提供了可选参数 userdata ,将被作为第三个参数传递给回调函数。 如果 function 函数需要的参数比给出的多,则每次 array_walk() 调用 function 时都会产生一个 E_WARNING 级的错误。这些警告可以通过在 array_walk() 调用前加上 PHP 的错误操作符 @ 来抑制,或者用 error_reporting()。 语法: ``` bool array_walk ( array &$array , callable $callback [, mixed $userdata = NULL ] ) ``` **array** 必需。规定输入的数组。 **callback** 必需。用户自定义函数的名称。 典型情况下 callback 接受两个参数。array 参数的**值**作为第一个,**键**名作为第二个。 ```php $school = ['first'=>'QinHua','second'=>'BaiDa','third'=>'ZheDa']; function print_school_array($val, $key) { echo $key . ' : ' . $val . "\n"; } array_walk($school,'print_school_array'); // echo 结果 first : QinHua second : BaiDa third : ZheDa // 使用匿名函数也是同样的结果 array_walk($school, function ($val, $key) { echo $val . ' : ' . $key . "\n"; }); ``` **userdata** 可选。用户输入的值,可作为回调函数的参数。 如果提供了可选参数 userdata,将被作为第三个参数传递给 callback funcname。 **提示和注释** * 提示:您可以为函数设置一个或多个参数。 * 注释:如果回调函数需要直接作用于数组中的值,可以将回调函数的第一个参数指定为引用:&$value。(参见例子 3) * 注释:将键名和 userdata 传递到 function 中是 PHP 4.0 新增加的。 **案例** * 打印数组中的值和键 ```php function myfunction($value, $key) { echo "$key has the value $value \n"; } $a = ["a" => "Cat", "b" => "Dog", "c" => "Horse"]; array_walk($a, "myfunction"); // 打印结果 a has the value Cat b has the value Dog c has the value Horse ``` * 带有一个参数 ```php function fun_param($value, $key,$param) { echo "KEY=$key Value=$value Param=$param \n"; } $arr = ["a" => "Cat", "b" => "Dog", "c" => "Horse"]; array_walk($arr,'fun_param','Tinywan'); // 打印结果 KEY=a Value=Cat Param=Tinywan KEY=b Value=Dog Param=Tinywan KEY=c Value=Horse Param=Tinywan ``` * 改变数组元素的值(请注意` &$value`):(这种情况用的比较多!) ```php function fun_value(&$value, $key,$param) { $value = $value.'-'.$param; } $arr = ["a" => "Cat", "b" => "Dog", "c" => "Horse"]; print_r($arr); array_walk($arr,'fun_value','[school]'); print_r($arr); // 打印结果 Array ( [a] => a:Cat-[school] [b] => b:Dog-[school] [c] => c:Horse-[school] ) ``` >[danger] 注意,第一个参数数组传递的是引用而不是传值 * 官方案例 ```php $school = ['first' => 'QinHua', 'second' => 'BaiDa', 'third' => 'ZheDa']; function print_school_array($val, $key) { echo $key . ' : ' . $val . "\n"; } function user_school_array(&$val, $key,$user_data) { $val = "($user_data) $val"; } array_walk($school,'user_school_array','Tinywan'); array_walk($school,'print_school_array'); // echo 结果 first : (Tinywan) QinHua second : (Tinywan) BaiDa third : (Tinywan) ZheDa ``` * 匿名函数实现 ```php $school = ['first' => 'QinHua', 'second' => 'BaiDa', 'third' => 'ZheDa']; $user_data = 'AI'; array_walk($school,function (&$val, $key) use ($user_data){ $val = "[$user_data] $val"; }); array_walk($school,'print_school_array'); // echo 结果 first : [AI] QinHua second : [AI] BaiDa third : [AI] ZheDa ``` >[info] array_walk()与 array_map() 的区别 区别与总结: * array_walk() 主要用于对某个数组的迭代,相当于 foreach; * array_map() 主要是根据某个/某几个数组产生一个新的数组,常应用于递归效果! 详解 * [PHP数组函数: array_walk()](http://www.cnblogs.com/52php/p/5675330.html) * [PHP数组函数: array_map()](http://www.cnblogs.com/52php/p/5675331.html) >[info] 案例 06 `call_user_func `函数 把第一个参数作为回调函数调用 语法: ``` mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] ) ``` > 第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。 * 一个参数 ```php function say($name){ echo $name." is saying"; } call_user_func('say','Tinywan'); // 输出:Tinywan is saying ``` * 两个参数 ```php function what($name,$event){ echo $name." is ".$event; } call_user_func('what','Tinywan','song'); // 输出:Tinywan is song ``` * 没有参数 ```php function test(){ echo __FUNCTION__." is test"; } call_user_func('test'); ``` * 系统函数 ```php echo call_user_func('md5','123456'); // 10adc3949ba59abbe56e057f20f883e- ``` * 多个参数,使用`call_user_func_array()`函数 ```php function foobar($arg, $arg2) { echo __FUNCTION__, " got $arg and $arg2\n"; } call_user_func_array("foobar", array("one", "two")); // foobar got one and two // 加法运算 function add($v1,$v2){ return $v1 + $v2; } echo call_user_func_array('add',[12,23]); ```