码迷,mamicode.com
首页 > Web开发 > 详细

PHP回调函数--call_user_func_array

时间:2015-06-02 21:27:35      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:

全局函数的回调

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

 示例代码

$msg1 , $msg2 )
技术分享{
技术分享    echo msg1:.$msg1;
技术分享    echo "<br />\n";
技术分享    echo msg2:.$msg2;
技术分享}
技术分享$fnName = "fnCallBack";
技术分享$params = arrayhello , world );
技术分享call_user_func_array$fnName , $params );


代码说明:

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


效果如下:

技术分享


类的静态方法的回调

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

示例代码:

{
技术分享    public static function fnCallBack( $msg1 , $msg2 )
技术分享    {
技术分享        echo msg1:.$msg1;
技术分享        echo "<br />\n";
技术分享        echo msg2:.$msg2;
技术分享    }
技术分享}
技术分享
技术分享$className = MyClass;
技术分享$fnName = "fnCallBack";
技术分享$params = arrayhello , world );
技术分享call_user_func_arrayarray$className , $fnName ) , $params );



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

运行结果:

技术分享
(其实和第1种方法的结果是一样的 ^_^ )


继续研究

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

{
技术分享    public function fnCallBack( $msg1 , $msg2 )
技术分享    {
技术分享        echo msg1:.$msg1;
技术分享        echo "<br />\n";
技术分享        echo msg2:.$msg2;
技术分享    }
技术分享}
技术分享
技术分享$className = MyClass;
技术分享$fnName = "fnCallBack";
技术分享$params = arrayhello , world );
技术分享call_user_func_arrayarray$className , $fnName ) , $params );


运行结果
技术分享

和前面的结果还是一样的。。。


现在我为这个类添加一点属性,并在方法中引用

{
技术分享    private $name = abc;
技术分享    public function fnCallBack( $msg1 , $msg2 )
技术分享    {
技术分享        echo object name:.$this->name;
技术分享        echo "<br />\n";
技术分享        echo msg1:.$msg1;
技术分享        echo "<br />\n";
技术分享        echo msg2:.$msg2;
技术分享    }
技术分享}
技术分享
技术分享$className = MyClass;
技术分享$fnName = "fnCallBack";
技术分享$params = arrayhello , world );
技术分享call_user_func_arrayarray$className , $fnName ) , $params );


运行结果
技术分享

出现解析错误,提示$this没有在对象环境下出现,说明这个方法不能用类来调用,而是要用对象来调用。那我们就修改一下代码,创建一个对象:

{
技术分享    public function fnCallBack( $msg1 , $msg2 )
技术分享    {
技术分享        echo msg1:.$msg1;
技术分享        echo "<br />\n";
技术分享        echo msg2:.$msg2;
技术分享    }
技术分享}
技术分享
技术分享$myobj = new MyClass();
技术分享$className = myobj;
技术分享$fnName = "fnCallBack";
技术分享$params = arrayhello , world );
技术分享call_user_func_arrayarray$className , $fnName ) , $params );


运行结果:
技术分享


提示call_user_func_array的第1个参数非法,也就是说,调用失败。看来我们不能用call_user_func_array方法来回调一个对象的方法了,那么如何实现对象方法的回调的?


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

{
技术分享    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 = arrayhello , world );
技术分享$myobj->$fnName();


成功了,输出结果
技术分享


调用是成功了,不过如何把参数params传给这个方法呢,如果把params直接传进去,那么它会作为1个参数,怎么把params拆开来传进去呢?

查了下PHP手册,找到了create_function函数,这个方法可以用字符串来创建一个匿名函数,好,有思路了,可以创建一个匿名的函数,在这个匿名函数中,调用我们的回调函数,并把参数传进去。

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

{
技术分享    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 = arrayhello , world );
技术分享
技术分享function anonymous()
技术分享{
技术分享    global $myobj;
技术分享    global $fnName;
技术分享    global $params;
技术分享    $myobj->$fnName$params[0, $params[1] );
技术分享}
技术分享anonymous();


 成功了,可以看到,对象的属性name也输出来了
技术分享


然后,我用create_function来创建这个匿名函数,同时,代码中的params[0],params[1]应该是动态生成的,代码如下:

= ‘‘;
技术分享$strCode = global $myobj;global $fnName;global $params;$myobj->$fnName(;
技术分享for ( $i = 0 ; $i < count$params ) ; $i ++ )
技术分享{
技术分享    $strParams .= ( $params[.$i.] );
技术分享    if ( $i != count$params )-1 )
技术分享    {
技术分享        $strParams .= ,;
技术分享    }
技术分享}
技术分享$strCode = $strCode.$strParams.");";
技术分享$anonymous = create_function‘‘ , $strCode);
技术分享$anonymous();



这段代码可以定义一个匿名函数,并保存在$anonymous变量中,最后调用这个$anonymous,实现了方法的回调,如图

技术分享


PHP事件模型(观察者模式)的实现思路


至此,PHP中的3种常见的函数类型(全局函数,类静态函数,对象的方法)都可以回调了,可以实现文章一开始说的事件模型了 :)

事件模型模仿Firefox的Javascript实现,有3个方法,分别是

技术分享addEventListener:注册一个事件上的响应回调函数
技术分享removeEventListener:删除一个事件上的响应回调函数
技术分享fire:触发一个事件,也就是循环调用所有响应这个事件的回调函数



    不过,由于第2、第3种方法需要传递上下文(也就是类名和对象名),所以addEventListener和removeEventListener应该有3个参数,我是这样设计的:

$evtName , $handler , $scope = null )

 
    第1个参数表示事件名,字符串类型
    第2个参数表示回调函数名,字符串类型
    第3个参数$scope是上下文环境,一共有3种类型,null表示传入的handler函数是一个全局函数,字符串类型表示传入的handler函数是scope类的静态函数,对象类型表示传入的scope是一个对象,handler函数是对象的一个方法。

$evtName , $params = null )


    这个方法内,会读取出所有响应evtName的handler,然后判断它对应的scope,如果是null,则用本文第1种方法回调,如果是字符串,则 用本文第2种方法回调,如果是对象,则用本文第3种方法回调。这样,一个PHP的事件模型就可以实现了,而且可以将回调函数放在某个对象中。

PHP回调函数--call_user_func_array

标签:

原文地址:http://www.cnblogs.com/zzl-21086595/p/4547519.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!