首页 > 代码库 > 回调、匿名函数和闭包

回调、匿名函数和闭包

(1) is_callable用来检测传进来的值能被call_user_func或者array_walk等函数使用,它非常智能,能够测试数组,数组形式的有效回调应该是以对象作为第一个元素,以方法名作为第二个元素,类似 array(‘new SomeClass()‘, ‘someFunc‘)。

下面用例子来说明:

 1 function a(){ 2  3 } 4  5 $a = ‘a‘; 6  7 if(is_callable($a)){ 8  9     echo ‘a is callable <br>‘;10 11 } else {12 13     echo ‘a is not callable <br>‘;14 15 }

输出:

1 a is callable 
 1 class B{ 2  3     public function add($arg = []){ 4  5         echo ‘sum: ‘ . ($arg[0] + $arg[1]) . ‘<br>‘; 6  7     } 8  9 }10 11 $c = [new B(), ‘add‘];12 13 if(is_callable($c)){14 15     call_user_func($c, [1, 2]);16 17 }

输出:

1 sum: 3

(2) array_walk 将用户自定义函数应用到数组中的每一个元素。

例子:

 1 $array = [1, 2, 3]; 2  3 function show($v, $k, $u){ 4  5     $v += 1; 6  7     echo "u: {$u}, k: {$k}, v: {$v}<br>"; 8  9 }10 11 array_walk($array, ‘show‘, ‘Jerry‘);12 13 echo ‘<pre>‘;14 15 print_r($array);

在这个例子中,需要注意,array_walk函数第一个参数为数组名,第二个参数为回调函数名,第三个为用户自定义参数,在本例中,show函数的第一个参数为数组$array的值,第二个参数为数组$array的键值或者索引,第三个参数为用户自定义参数,对应着array_walk的第三个参数,本例输出如下:

 1 u: Jerry, k: 0, v: 2 2 u: Jerry, k: 1, v: 3 3 u: Jerry, k: 2, v: 4 4  5 Array 6  7 ( 8  9     [0] => 110 11     [1] => 212 13     [2] => 314 15 )

如果想在show函数处理完之后同时改变原数组$array的值,可以在show函数的第一个参数前使用&引用地址符,示例如下:

 1 $array = [1, 2, 3]; 2  3 function show(&$v, $k, $u){ 4  5     $v += 1; 6  7     echo "u: {$u}, k: {$k}, v: {$v}<br>"; 8  9 }10 11 array_walk($array, ‘show‘, ‘Jerry‘);12 13 echo ‘<pre>‘;14 15 print_r($array);

通过改变$v的值,同时改变数组$array的值,输出:

 1 u: Jerry, k: 0, v: 2 2 u: Jerry, k: 1, v: 3 3 u: Jerry, k: 2, v: 4 4  5 Array 6  7 ( 8  9     [0] => 210 11     [1] => 312 13     [2] => 414 15 )

(3) call_user_func将其第一个参数作为回调函数使用,其余参数当做该回调函数的参数。

 1 function d($a, $b, $c){ 2  3     echo "a: {$a}, b: {$b}, c: {$c}<br>"; 4  5 } 6  7 $f = ‘d‘; 8  9 if(is_callable($f) && function_exists($f)){10 11     call_user_func($f, ‘Kue‘, ‘Sub‘, ‘Dod‘);12 13 }

输出:

1 a: Kue, b: Sub, c: Dod

(4) create_function创建匿名函数,第一个参数为该匿名函数的参数,第二个参数为匿名函数的函数体。

1 $n = create_function(‘$a, $b‘, ‘return $a + $b;‘);2 3 echo $n(1,2).‘<br>‘;

输出:3

其中,这个例子需要注意的地方是,第二个参数语句完成之后不要忘记加分号,如果不加会报错,错误信息如下:

1 Parse error:  syntax error, unexpected ‘}‘, expecting ‘;‘ in : runtime-created function on line 1

(5) 在PHP5.3以后,有更好的方式来实现create_function的功能,这就是内联函数的使用。

1 $e = function($arg){2 3     echo "arg: {$arg}<br>";4 5 };6 7 $e(‘Hello world!‘);

这是内联函数的基本用法,其中函数体结束需要以分号结束,本例会输出:

1 arg: Hello world!

(6) 闭包 use

 1 function message($m){ 2  3     $close = ‘door‘; 4  5     $h = function($m) use(&$close, $m){ 6  7         echo "{$m} close the {$close} please!<br>"; 8  9         $close = ‘nali‘;10 11     };12 13     $h(‘Lily‘);14 15     echo $close.‘<br>‘;16 17 }18 19 echo call_user_func(‘message‘, ‘Jim‘);

输出:

1 Jim close the door please!2 3 nali
本例中 use 关键字将变量$close与内联函数$h连接在一起,如果$close前面不加&地址符,则$close的值不会改变,加上&之后,$close的值会随之改变。

回调、匿名函数和闭包