回调函数的原理及PHP实例

背景:在最近的一个开发项目中,用户要先调用服务才能开始进行一系列的查询活动,想了好久,经同事提醒, 用回调函数即可解决该问题。在这里,对PHP下回调函数的原理及实现分别做一下讲解。

1 什么是回调

软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础,因此,下面我们着重讨论回调机制在不同软件架构中的实现。

对于不同类型的语言(如结构化语言和对象语言)、平台(Win32、JDK)或构架(CORBA、DCOM、WebService),客户和服务的交互除了同步方式以外,都需要具备一定的异步通知机制,让服务方(或接口提供方)在某些情况下能够主动通知客户,而回调是实现异步的一个最简捷的途径。对于一般的结构化语言,可以通过回调函数来实现回调。回调函数也是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。

在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类成为回调类,回调类的对象成为回调对象。对于象C++或Object Pascal这些兼容了过程特性的对象语言,不仅提供了回调对象、回调方法等特性,也能兼容过程语言的回调函数机制。Windows平台的消息机制也可以看作是回调的一种应用,我们通过系统提供的接口注册消息处理函数(即回调函数),从而实现接收、处理消息的目的。由于Windows平台的API是用C语言来构建的,我们可以认为它也是回调函数的一个特例。对于分布式组件代理体系CORBA,异步处理有多种方式,如回调、事件服务、通知服务等。事件服务和通知服务是CORBA用来处理异步消息的标准服务,他们主要负责消息的处理、派发、维护等工作。对一些简单的异步处理过程,我们可以通过回调机制来实现。

2 PHP的回调函数的实现方法

2.1 全局函数的回调

这里的全局函数的意思,是直接使用function定义的函数,它不包含在任何对象或类之中。请看下面的例子

function fnCallBack( $msg1 , $msg2 )

{

echo ‘msg1:‘.$msg1;

echo "<br />\n";

echo ‘msg2:‘.$msg2;

}

$fnName = "fnCallBack"; //方法名

$params = array( ‘hello‘ , ‘world‘ );//传给参数的值

call_user_func_array( $fnName , $params );

结果:

代码说明:

这里使用了PHP内置的函数call_user_func_array来进行调用。call_user_func_array有两个参数,第1个参数是一个字符串,表示要调用的函数名,第2个参数是一个数组,表示参数列表,按照顺序依次会传递给要调用的函数。

2.2 类的静态方法的回调

如果我们要回调的方法,是一个类的静态方法,那怎么办呢?我们依然可以利用PHP内置的call_user_func_array方法来进行调用,请看示例:

示例代码:

class MyClass

{

public static function fnCallBack( $msg1 , $msg2 )

{

echo ‘msg1:‘.$msg1;

echo "<br />\n";

echo ‘msg2:‘.$msg2;

}

}

$className = ‘MyClass‘; //类名

$fnName = "fnCallBack";//类中的方法名

$params = array( ‘hello‘ , ‘world‘ );//传给参数的值

call_user_func_array( array( $className , $fnName ) , $params );

结果:

代码说明:

这段代码和第1种方法的代码很相似,我们将类名(MyClass)也作为call_user_func_array的第1个参数传递进去,就可以实现类的静态方法的回调了。注意,这时call_user_func_array的第1个参数是一个数组了,数组的第1个元素是类名,第二个元素是要调用的函数名

如果我用这种方法调用一个类的非静态方法(也就是把static去掉),会出现什么结果呢?请看下面代码

class MyClass

{

public function fnCallBack( $msg1 , $msg2 )

{

echo ‘msg1:‘.$msg1;

echo "<br />\n";

echo ‘msg2:‘.$msg2;

}

}

$className = ‘MyClass‘;

$fnName = "fnCallBack";

$params = array( ‘hello‘ , ‘world‘ );

call_user_func_array( array( $className , $fnName ) , $params );

最终运行的结果跟原来一样

2.3 对象的方法的回调

我先用最原始的字符串形式的调用方法尝试了一下,如下所示:

class MyClass

{

private $name = ‘abc‘;

public function fnCallBack( $msg1 = ‘default msg1‘ , $msg2 = ‘default msg2‘ )

{

echo ‘object name:‘.$this->name;

echo "<br />\n";

echo ‘msg1:‘.$msg1;

echo "<br />\n";

echo ‘msg2:‘.$msg2;

}

}

$myobj = new MyClass();

$fnName = "fnCallBack";

$params = array( ‘hello‘ , ‘world‘ );

$myobj->$fnName();

结果:

调用是成功了,不过如何把参数params传给这个方法呢,如果把params直接传进去,那么它会作为1个参数,怎么把params拆开来传进去呢?查了下PHP手册,找到了create_function函数,这个方法可以用字符串来创建一个匿名函数,好,有思路了,可以创建一个匿名的函数,在这个匿名函数中,调用我们的回调函数,并把参数传进去。

我先手动创建一个匿名函数anonymous,在这个函数中,用前面试出来的方法调用回调函数,如下所示:

class MyClass

{

private $name = ‘abc‘;

public function fnCallBack( $msg1 = ‘default msg1‘ , $msg2 = ‘default msg2‘ )

{

echo ‘object name:‘.$this->name;

echo "<br />\n";

echo ‘msg1:‘.$msg1;

echo "<br />\n";

echo ‘msg2:‘.$msg2;

}

}

$myobj = new MyClass();

$fnName = "fnCallBack";

$params = array( ‘hello‘ , ‘world‘ );

//匿名函数的构建

function anonymous()

{

global $myobj;

global $fnName;

global $params;

$myobj->$fnName( $params[0] , $params[1] );

}

anonymous();

成功了。效果如下:

参考文献:

http://myceo.blog.51cto.com/2340655/725411/

http://blog.chinaunix.net/uid-20684384-id-1895266.html

http://segmentfault.com/a/1190000002901770

http://www.abc3210.com/2012/phper_07/php-callback.shtml

非常感谢以上的参考文献以及博主!

版权声明:Hello,很高兴能在CSDN上和大家相遇!希望能和大家交上朋友!

时间: 2024-12-18 19:30:41

回调函数的原理及PHP实例的相关文章

javascript回调函数(模式)原理和示例深入分析

   广大网友读懂了我之前论述的javascript原理这篇文章很容易懂 回调函数来自一种著名的编程范式--函数式编程,在基本层面上,函数式编程指定的了函数的参数.函数式编程虽然现在的使用范围变小了,但它一直被"专业的聪明的"程序员看作是一种难懂的技术,以前是这样,未来也将是如此. 幸运的是,函数式编程已经被阐述的像你我这样的一般人也能理解和使用.函数式编程最主要的技术之一就是回调函数,你很快会阅读到,实现回调函数就像传递一般的参数变量一样简单.这项技术如此的简单,以至于我都怀疑为什么

关于jQuery回调函数的定义及用法实例

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset=" utf-8"> 5 <meta name="author" content="http://www.jb51.net/" /> 6 <title>脚本之家</title> 7 <style type="text/css"> 8

nodejs批量导入数据eventproxy(回调函数嵌套解决方案)使用实例

回调函数嵌套解决方案——eventProxy API地址:https://github.com/JacksonTian/eventproxy 1.安装eventproxy 执行npm install eventProxy. 2.使用前进行声明,代码如下: var EP = require('eventproxy'); 3.根据API进行相应的方法调用,代码如下: ajax.post('/user/login', { name: '********', pwd: '******', remembe

c++与java中的回调函数

首先,说明一下,因为java中没有指针的概念,所以java与c++中回调函数虽然原理差不多,但是实现方法不同. 说实话,如果c++是简单暴力直接的话,java更像一个小姑娘扭扭捏捏,本人也是过了很多次才了解到这个用法.... 1.c++ c++中的简单极了,只要将要调用的函数地址传给函数指针即可,简单明了.如下 #include <iostream> using namespace std; void pig() { cout << "猪在叫叫叫!!" <

js回调函数(callback)理解

Mark! js学习 不喜欢js,但是喜欢jquery,不解释. 自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函数了.不懂啊,于是在google回调函数,发现网上的中文解释实在是太“深奥”了,我承认自己才疏学浅了.看了几个回调的例子后,貌似有点理解了.下面是我对回调函数的理解,要是理解错了,请指正,不甚感激. 首先还是从jquery网站上的英文定义入手,身为国人,我真感到悲剧.一个回调的定义被国内的“高手”解

Block、委托、回调函数原理剖析(在Object C语境)——这样讲还不懂,根本不可能!

开篇:要想理解Block和委托,最快的方法是搞明白“回调函数”这个概念. 做为初级选手,我们把Block.委托.回调函数,视为同一原理的三种不同名称.也就是说,现在,我们把这三个名词当成一回事.在这篇文章内,Block就是回调函数,委托也是回调函数,不再作详细的区分了.OK,Action! 那么,什么是回调函数?“回调”概念的主语是谁? 举个栗子(伪代码): 首先有个类,我们姑且称之为A类吧. A.h 文件 //声明回调函数:给指定的员工发放工资 -(void)paySalaryForStaff

Jquery回调函数应用实例解析

jQuery代码中对回调函数有着广泛的应用,对其有精准的理解是非常有必要的,下面就通过实例对此方法进行简单的介绍. 代码实例如下: 利用回调函数,当div全部隐藏之后弹出一个提示框. <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="http://www.jb51.net/" /

实例介绍 Java(android) 回调函数使用方法

在Android开发中经常用到回调机制,其中最典型的就是控件被触发的实现方式,简单而言,如Button被Click后,是系统调用了OnClick方法,而我们为Button注册了OnClickListener监听器,当被触发Click后,OnClickListener中的OnClick方法就会被回调,我们就能在其中执行相应操作了. 下面举一个简单的例子介绍回调的实现方式: 回调函数使用的简单例子 程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序.程序员B要让a调用自己的程序

回调函数教程(一):回调函数定义及用接口实现的实例

回调函数定义: 传递一个函数A到另一个函数B中,并且这个函数B执行函数A.我们就说函数A叫做回调函数.如果没有名称,就叫做匿名回调函数.或者将一个方法对象A 传递给另一个方法对象 B,让后者在适当的时候执行A,那么A就叫做回调函数. 回调函数实例理解: 消防员给出一个电话号码119(这是每个人都知道的,119就相当于Java中的一个接口),并且在每一个地方都设置一个发生火灾时的检测装置,如果危急到人们的人生安全时,那么市民就可以通过119给消防员打电话,然后叫消防员来处理.回调的意思就是说,消防