『PHP』浅析callback回调函数

586 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

努力学习中,目前对回调函数的思想还是不能很好地理解,如有错误欢迎前往评论区留言

一、callback回调函数定义

回调函数(callback)是什么? - 知乎 (zhihu.com)

回调函数(callback)是什么? - 知乎精选评论1 (zhihu.com)

回调函数(callback)是什么? - 知乎精选评论2 (zhihu.com)

直接运行一个函数被称为直调

# 直调
<?php
function hello(){
	echo "hello";
}

hello();

而通过一个函数(中间函数)调用另一个函数(回调函数)被称为回调,中间函数已经定义好回调函数执行完成后的其他动作了,我们在主程序直接调用此中间函数即可

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

# 回调
# run()是中间函数
# hello()是回调函数
# 回调是通过call_user_func()实现的
<?php
function run($func, $param){
  	call_user_func($func, $param);
  	echo "Run done!<br/>";
}
function hello($param){
    echo "hello".$param."<br/>";
  }
  
run("hello", 1);

“你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。回答完毕。“

(摘自知乎 作者:常溪玲)

二、call_user_func()和call_user_func_array()

PHP使用call_user_func()和call_user_func_array()回调

# 函数原型
call_user_func ( callable $callback , mixed $parameter = ? , mixed $... = ? ) : mixed

call_user_func_array ( callable $callback , array $param_arr ) : mixed

二者区别在于前者传参上散装的,后者传参上需要封成array

三、回调的实现

Ⅰ、回调普通函数

<?php
function test($a, $b){
	echo $a.$b."<br/>"
}

call_user_func('test', 1, 2);
call_user_func_array('test', array(1, 2));

Ⅱ、回调类函数

第一个传参为array,包含对象名和函数名,需实例化

<?php
class Test{
  function t1($a){
     echo 't1 '.$a.'<br/>';
   }
  public static t2($a){
     echo 'static t2'.$a.'<br/>';
   }
}

$test = new Test();
call_user_func(array($test, 't1'), 1);

Ⅲ、回调类静态函数

第一个传参为array,包含类名和函数名,无需实例化

<?php
 class Test{
  function t1($a){
     echo 't1 '.$a.'<br/>';
   }
  public static t2($a){
     echo 'static t2'.$a.'<br/>';
   }
}

call_user_func(array('Test', 't2'), 1);

四、为什么不采用$func()?

回到最开始的示例代码

<?php
function run($func, $param){
	call_user_func($func, $param);
	echo "Run done!<br/>";
}
function hello($param){
	echo "hello".$param."<br/>";
}
 
run("hello", 1);

最开始很是不能理解为什么不修改成以下的写法:

<?php
function run($param){
	hello($param); # changed
	echo "Run done!<br/>";
}
function hello($param){
	echo "hello".$param."<br/>";
}

run(1);

回调和直调其实并无区别,回调只是借助了一个中间函数间接调用另一个函数

使用回调的目的是:run函数可能是一个系统级函数、或者是其他我们无权修改的函数,而hello这个函数我们是可以自定义的,因此在中间函数调用的时候不能写的太具体,通过传参来达到一个类似接口的操作,这种采用回调的方法提高了中间函数-回调函数的灵活性:

<?php
function run($func, $param){
	call_user_func($func, $param);
	echo "Run done!<br/>";
}
function hello($param){
	echo "hello".$param."<br/>";
 }
function nihao($param){
	echo "nihao".$param."<br/>";
 }
function bonjour($param){
	echo "bonjour".$param."<br/>";
 }
 
run("hello", 1);
run("nihao", 2);
run("bonjour", 3);

如果打算新添加函数,那么在中间函数使用回调就很方便灵活了,直接对中间函数传入新添加的回调函数名称即可运行,这就体现了回调函数提高灵活性的作用了