您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

回调函数的原理及PHP实例

2024/10/13 9:04:00发布28次查看
背景:在最近的一个开发项目中,用户要先调用服务才能开始进行一系列的查询活动,想了好久,经同事提醒, 用回调函数即可解决该问题。在这里,对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
\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
\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
\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
\n;
        echo 'msg1:'.$msg1;
        echo
\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
\n;
        echo 'msg1:'.$msg1;
        echo
\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上和大家相遇!希望能和大家交上朋友!
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product