![PHP面试一战到底](https://wfqqreader-1252317822.image.myqcloud.com/cover/891/44509891/b_44509891.jpg)
2.7 回调函数
2.7.1 概念
回调函数(callbacks)类型可以将一个函数作为变量或参数传递给其他函数使用。在PHP中,诸如call_user_func、call_user_func_array、usort、uasort、uksort等函数,都可以接收一个函数作为参数。
为了演示回调函数的使用,我们举例如下,对以下数据按成绩高低进行排序。
使用到的函数usort(http://php.net/manual/zh/function.usort.php)定义如下:
bool usort ( array &$array , callable $value_compare_func )
参数array为参与排序的数组;value_compare_func是回调函数,用于比较两个数a和b的大小,大于时返回1,等于时返回0,小于时返回-1。
对表2-7中的数据按照成绩进行排序。
表2-7 成绩排序示例
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-T48_39605.jpg?sign=1739342195-Qa8vUpxp37iTTxHWQVgUEhc4JjnIrKsg-0-5a1eb411003fe0781ba10a40934cd1ca)
程序代码如下:(源码文件:ch02/callback_usort.php)
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P48_39603.jpg?sign=1739342195-RxILhSjjqLhpZgoGB5dkbMnzL64LDECE-0-c91cfc756b4f466abb8f13c052d74773)
输出结果如下:
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P48_39604.jpg?sign=1739342195-QRKwtt4LwHmaVj9JJGC7kTbDyNH5BXDM-0-4f955420ded2923fab214e8c91635add)
2.7.2 回调函数的使用
PHP中的call_user_func()函数和call_user_func_array()函数都是回调函数,在写接口的时候经常会用到,但是它们有什么区别呢?
call_user_func()函数不支持引用参数,而call_user_func_array()支持引用参数,两者传入参数的方式不同。参见下述程序代码,观察两个回调函数的用法:
<?php function u_add($a1,$a2){ return $a1+$a2; } echo call_user_func('u_add',1,2); echo call_user_func_array('u_add',[1,2]);
这两个回调函数的第一个参数都是被调用的回调函数,call_user_func()还可以有多个参数,它们都是回调函数的参数,call_user_func_array()只有两个参数,第二个参数是要被传入回调函数的数组,这个数组得是索引数组。
如果传递一个数组给call_user_func_array(),数组的每个元素的值都会被当作一个参数传递给回调函数,数组的key回调掉。
如果传递一个数组给call_user_func(),整个数组会当作一个参数传递给回调函数,数组的key还会保留住。
比如有如下的回调函数:
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P49_39607.jpg?sign=1739342195-B24PCWzeBjox2YIgt17o8l2xjyJJMjim-0-036d5203c5d240becb6e9be70ad7826d)
我们分别使用call_user_func函数和call_user_func_array函数进行回调:
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P49_39608.jpg?sign=1739342195-5kj6rvItSCW06DJ2KoMWauOxzmWpMO4U-0-503293120ef4c5255d4b17f8ead683f9)
最后输出结果:
1个参数:
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P49_39610.jpg?sign=1739342195-ZC3hDcKTX1mAXOehEc6XveaEHvtqKlL1-0-44dbbddf30012dd60eabe8ee1882277d)
3个参数:
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P50_39612.jpg?sign=1739342195-PwnvHXV0eS5FhliNcL6FfXt3mbM5YE5a-0-3ca2d6031f3b33b6a7454269ad101014)
2.7.3 面试题:call_user_func()和call_user_func_array()的区别
题目描述:请说明call_user_func()和call_user_func_array()的区别有哪些?
解答:call_user_func()和call_user_func_array()都可以调用一个用户自定义的回调函数,它们的定义如下:
mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] ) mixed call_user_func_array ( callable $callback , array $param_arr )
可以看到,两个函数的第一个参数都是callback函数,不同之处有两个:
(1)参数数目不同。call_user_func可以接收多个参数,包括可变数量的参数;而call_user_func_array可接收一个数组作为参数。
(2)对引用传递参数的处理不同。call_user_func只能进行值传递,无法进行引用传递。而call_user_func_array支持引用传递。为加深大家的理解,我们看下面的代码示例。
(源码文件:ch02/callback_reference.php)
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P50_39618.jpg?sign=1739342195-jBG80qW2j5kM0G443SmqvqBk8l7Q6cjt-0-657a62bcc4525ad7f8d2ef67102dc2e6)
第2行定义了一个demo函数,其参数$a为引用传递参数。
第6行用call_user_func_array调用demo函数,并将$a=6以引用形式传递。
这时输出的$a=5,因为$a在demo函数里被重新赋值为5。
第8行用call_user_func调用demo函数,这是语法不允许的,直接抛出如下错误:
Fatal error: Call-time pass-by-reference has been removed