PHP 中使用回调函数(callback function)实现业务逻辑
今天的话题是PHP回调函数。
很久之前啊,在我的PHP水平到达了愚昧之山(
“愚昧之山”来自著名的达克效应
)的水平的时候,以为自己很厉害了,可以去接触一门新的语言了的时候,我把目光移向了JavaScript。当我玩到AJAX的时候,马上就被JavaScript的回调函数吸引到了:卧槽居然代码还能这么写?函数也能当成一个变量类型,然后把函数当成参数传过去?
后来……后来我就封装了一个微信web开发时初始化用的函数,在这个js文件里:http://www.dxever.com/xt_web/js/xt.js
后来当我回到php写代码的时候(毕竟主业还是php… ,在一遍又一遍复制一些验证性功能的代码的时候,我就想:能不能把一些验证性功能的代码封装成回调函数,每次只需要调用就可以了。
研究了一阵之后,答案是可以的。
我们先看一下,回调实现前我们要面临的问题。首先我们得编出一个例子,比如说我有一个相册的项目,每个人都可以自己建立自己的相册,所有相册在一个广场里,可以给所有人看,但是每个人只能改动自己的相册。如果一个人想修改自己的相册,需要验证正在操作的人是不是相册的主人,假装的代码是:
$album = M('album') -> where(['aid' => $aid]) -> field('userid') -> find();
if($userid == $album['userid']){
//修改相册
}else{
//不让修改
}
这个模板就写好了,然后每次都去复制这个模板。当我写完了添加相片、删除相片、修改相册名、删除相册…………等等功能后,这段代码也让我复制烂了。这样对代码空间很不友好,新浪云超出1M就要多交一份钱……然后也没法体现代码的重(chóng)用性,最重要的是——PHP程序员的代码怎么能没有逼格!要知道
PHP可是世界上最美的语言啊!
然后我想到能不能用回调函数实现这个业务逻辑。如果js在这也好使的话,应该是这样写的:
function confirmAlbunAuthor(userid,album_id,success_cb,failed_cb){
album = M('album') -> where({'aid' : album_id}) -> field('userid') -> find();
if(userid == album.userid){
success_sb();
}else{
failed_cb();
}
}
这个回调函数写好了之后,在需要使用的时候只需要这样调用就可以了:
function addPhoto(album_id,userid){
confirmAlbumAuthor(userid,album_id,function(){
//addPhoto
},function(){
//error
})
}
理想贼美好,现实却不是这样的。在PHP中实际实施的时候,面临这么几个问题:
首先,回调是为了解决在js中全部是异步执行的问题,让各种操作按照coder的意愿来依次执行用的(比如ajax);
然后……PHP对回调支持得并不是很好,尤其是传值问题…
虽然有困难,但也不是不能实现……牛批的PHP程序员还有什么实现不了的呢…
为了实现PHP的回调,我们需要准备这么几个知识点:
调用自定义函数:call_user_func_array(
获取参数列表:func_get_args()
php回调的传值顺序是这样的。
假设我们有回调函数A,和调用函数A的B函数。我们需要在B中获取B的参数列表a,在调用A的时候把a传过去,进行相关处理之后A 要把这个a再传回B,B中调用的A才能使用这个参数列表。为什么呢?就是因为不是同一层函数,没法取到这些参数值。
那返回值就更复杂了,我们直接看例子吧——在下面的举例子环节,我拿出了我们最近正在开发的项目——问卷。其中有一个业务逻辑,就是在变动问卷的时候需要验证正在编辑问卷的用户是不是该问卷的作者。其实跟上面举的相册的例子是一回事。
首先放出我们的回调函数A:
然后是调用A 的函数B:
在代码中我们看到,我们要做的事情实际上是B,B函数中直接调用A,获取到了参数列表(func_get_args()),然后代码运行到了函数A。A接受到了参数列表,进行相关处理,然后根据不同结果执行了对应的两个回调函数。成功的时候,回调函数将参数列表带了回来,此时代码回到B中,我们在function的括号中调用了刚才传回来的参数,进行接下来的业务逻辑。失败的时候,我就没把那个参数列表带回来,因为只需要告诉用户失败了就可以了。
返回值……解释如下图
实在不行就自己用手抠着代码找吧……实在是没法靠打字来讲明白。
这样的话php回调就实现了,我们再敲一遍黑板:
调用自定义函数:
call_user_func_array($function,$paramArray)
获取参数列表:
func_get_args()
php回调的传值顺序。
实现了该需求之后,感觉代码的逼格又上来了,效率不知道如何,感觉应该和之前没差多少。然后…不建议刚学了几天php的同学就这么玩,有点作死…
结论是…
PHP不太适合回调,但要非这么写,也是可以的。
我是最会写段子的PHP程序员啊你亲爱的彤彤姐,如果觉得我写得因吹斯听,记得帮我把这篇文章分享到你的朋友圈,等我这个公众号盈利了,最初帮我转发的好人们也不一定会得到分红。