前言
回调函数是什么?
我们所谓的回调函数,就是指调用函数时,并不是传递一个标准的变量作为参数,而是将另一个函数作为参数传递到调用的函数中。如果在函数的格式说明中出现“callback”类型的参数,则该参数就是回调函数。callback也属于PHP中伪类型的一种,说明函数的参数需要接受另一函数作为实参。一个很重要的问题是为什么要使用函数作为参数,也就是为什么要使用回调函数呢,他解决了什么问题呢?我们带着疑问继续探索。在介绍函数参数的时候介绍过,通过参数的传递可以改变调用函数的执行行为,但有时候仅将一个值传递给函数能力还是有限的。如果可以将一个用户定义的“执行过程”传递到函数中使用,就大大增加了用户对函数功能的扩展。而如何声明和使用回调函数也是比较关键的问题,如果需要声明回调函数,就需要先了解一下变量函数。
什么是变量函数
变量函数也称为可变函数,如果一个变量名后有圆括号,PHP将寻找与变量的值同名的函数,并且将尝试执行它。例如,声明一个函数test(),将函数名称字符串“test”,赋值给变量$demo.如果直接打印$demo变量,输出的值一定是字符串“test”;但如果在$demo变量后加上圆括号“$demo()”,则为调用对应$demo变量值“test”的函数。这样就可以将不同的函数名称赋给同一个变量,再通过变量去调用这个函数,类似于面向对象中多态特性的应用。
回调函数的语法如下:
mixed funName (callback arg)
下面我们通过代码了解具体用法:
<?php
function sum($a,$b){
return $a + $b;
}
function multipl($a,$b){
return $a*$b;
}
function division($a,$b){
return $a/$b;
}
$result1 = "sum"; //将函数名sum赋值给变量$result1,执行$result1()时则调用函数sum()
$result2 = "multipl"; //将函数名multipl赋值给变量$result2,执行$result2()时则调用函数multipl()
$result3 = "division"; //将函数名division赋值给变量$result3,执行$result3()时则调用函数division()
echo "结果是:".$result1(4,6); //变量$result1接收到哪个函数名的值,就调用哪个函数
echo "\n";
echo "结果是:".$result2(4,6); //变量$result2接收到哪个函数名的值,就调用哪个函数
echo "\n";
echo "结果是:".$result3(4,6); //变量$result3接收到哪个函数名的值,就调用哪个函数
?>
执行结果如下:
在上例中声明了sum()、multipl()和division()三个函数,分别用于计算两个数的和、积、以及商。并将三个函数的函数名(不带圆括号)以字符串的方式分别赋给变量$result1、$result2、$result3,然后使用变量名$result1、$result2、$result3后面加上圆括号并传入两个整型参数,就会寻找与变量$result1、$result2、$result3的值同名的函数执行。大多数函数都可以将函数名赋值给变量,形成变量函数。但是变量函数不能用于语言结构,比如:echo(),print(), unset(),isset(),empty(),include(),require()以及类似的语句。
使用变量函数声明及应用回调函数
如果要自定义一个可以回调的函数,可以选择使用变量函数帮助实现。在定义回调函数时,函数声明结构是没有变化的,只要声明的参数是一个普通的变量即可。但在函数的内部应用这个参数变量时,如果加上圆括号就可以调用到和这个参数值同名的函数了,所以为其传值的参数一定要是另一个函数名称字符串才行。使用回调函数的目的是可以将一段自己定义的功能传到函数内部使用。具体代码如下所示:
<?php
//声明回调函数filter, 在0-30的整数中通过自定义条件过滤不要的数字
function filter($fun){
for($i=0; $i<=30; $i++){
//将参数变量$fun加上一个圆括号$fun(),则为调用和变量$fun值同名的函数
if($fun($i)){
continue;
}
echo $i."\r\n";
}
}
//声明一个函数one,如果参数是3的倍数就返回ture,否则返回false
function one($num){
return $num%3 == 0;
}
//声明一个函数two,如果参数是一个回文数返回ture,否则返回false
function two($num){
return $num == strrev($num);
}
filter("one"); //打印出30以内非3的倍数,参数one是函数one()的名称字符串,是一个回调
echo "---------------------\n";
filter("two"); //打印出30以内非回文数,参数two是函数two()的名称字符串,是一个回调
?>
执行结果如下:
在上面的例子中,如果声明的函数filter()只是接受普通的值作为参数,则用户能过滤掉的数字就会比较单一。而本例在定义的函数filter()调用到了通过参数传递进来的一个函数作为过滤条件,这样函数的功能就强大多了,可以在filter()函数中过滤掉你不喜欢的任意数字。在函数filter()内部通过参数变量$fun加上圆括号“$fun()”,就可以调用和变量$fun值相同的函数作为过滤的条件。比如:在上面的例子中,one()和two()两个函数,分别用于过滤30内3的倍数和回文数时,只要在调用 filter() 时将函数名称 one 和 two 字符串传递给参数,即将这两个函数传递给 filter() 函数内部使用