问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

php 框架 怎么使用回调函数

发布网友 发布时间:2022-04-25 18:06

我来回答

2个回答

热心网友 时间:2022-04-06 09:11

  前言
  最近在开发一个PHP系统,为了提高系统的扩展性,我想在系统中加入类似Javascript的事件处理机制,例如:我想在一篇新闻被添加以后,我想记录一下日志,用类似Javascript的代码,应该是这样写的:
  function fnCallBack( $news )
  {
  //将$news的信息记录到日志中
  writeLog( $news->getTitle().' has been added successfully!');
  }
  $newsEventManager->addEventListener( 'add' , fnCallBack );
  其中,fnCallBack函数是回调函数,addEventListener表示监听newsEventManager的add事件。当一篇news被add以后,系统就会调用fnCallBack函数,从而完成writeLog的动作。
  但是,PHP中的函数传递方法和Javascript有很大的不同。在Javascript中,函数也是对象,它可以很方便的当作参数传递,但是PHP不行。
  $newsEventManager->addEventListener( 'add' , fnCallBack );
  上面这行代码中的fnCallBack,看上去好像是那个函数的句柄,但实质上它是一个字符串,并不是我们所要的函数。
  为了实现我们的事件模型,有必要研究一下PHP的回调函数的实现方法。
  全局函数的回调
  这里的全局函数的意思,是直接使用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个参数是一个数组,表示参数列表,按照顺序依次会传递给要调用的函数。
  效果如下:
  类的静态方法的回调
  如果我们要回调的方法,是一个类的静态方法,那怎么办呢?我们依然可以利用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个元素是类名,第二个元素是要调用的函数名
  运行结果:
  (其实和第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 );
  运行结果
  和前面的结果还是一样的。。。
  现在我为这个类添加一点属性,并在方法中引用
  class MyClass
  {
  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 = array( 'hello' , 'world' );
  call_user_func_array( array( $className , $fnName ) , $params );
  运行结果
  出现解析错误,提示$this没有在对象环境下出现,说明这个方法不能用类来调用,而是要用对象来调用。那我们就修改一下代码,创建一个对象:
  class MyClass
  {
  public function fnCallBack( $msg1 , $msg2 )
  {
  echo 'msg1:'.$msg1;
  echo "<br />\n";
  echo 'msg2:'.$msg2;
  }
  }
  $myobj = new MyClass();
  $className = 'myobj';
  $fnName = "fnCallBack";
  $params = array( 'hello' , 'world' );
  call_user_func_array( array( $className , $fnName ) , $params );
  运行结果:
  提示call_user_func_array的第1个参数非法,也就是说,调用失败。看来我们不能用call_user_func_array方法来回调一个对象的方法了,那么如何实现对象方法的回调的?
  对象的方法的回调
  我先用最原始的字符串形式的调用方法尝试了一下,如下所示:
  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();
  成功了,可以看到,对象的属性name也输出来了
  然后,我用create_function来创建这个匿名函数,同时,代码中的params[0],params[1]应该是动态生成的,代码如下:
  $strParams = '';
  $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个参数,我是这样设计的:
  function addEventListener( $evtName , $handler , $scope = null )
  第1个参数表示事件名,字符串类型
  第2个参数表示回调函数名,字符串类型
  第3个参数$scope是上下文环境,一共有3种类型,null表示传入的handler函数是一个全局函数,字符串类型表示传入的handler函数是scope类的静态函数,对象类型表示传入的scope是一个对象,handler函数是对象的一个方法。
  function fire( $evtName , $params = null )
  这个方法内,会读取出所有响应evtName的handler,然后判断它对应的scope,如果是null,则用本文第1种方法回调,如果是字符串,则用本文第2种方法回调,如果是对象,则用本文第3种方法回调。这样,一个PHP的事件模型就可以实现了,而且可以将回调函数放在某个对象中。

热心网友 时间:2022-04-06 10:29

call_user_func()
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
请问哪位大哥“谨谢不敏”是什么意思? 小女子尽谢不敏什么意思 谨谢不敏是什么意思? 敬谢不敏是是什么意思? 谢不敏的意思是什么 谢不敏词语解释 什么叫“谢不敏”? 6岁儿童晚上睡眠不好怎么办 六岁孩子精神异常怎么办 小程序开发需要什么技术 没有技术如何开发小程序 php里面怎么为数组的每个元素应用回调函数? php回调函数是什么样子的 php中为什么的回调函数有什么作用呢?为什么不能直接调用自己的函数呢? 五行与气血的关系 PHP将回调函数作用到给定数组单元的方法 php中的回调函数到底什么意思,函数array_udiff的执行过程是什么样的,以... 如何判断自己是否气血虚? 关于PHP中函数的回调函数 气血是什么 回调函数什么概念,php中如何使用自定义的回调函数 气血阴阳营卫之间都是什么关系? 怎么理解回调函数?回调函数有什么好处 气血跟人体的关系 关于php回调函数的问题。下面是看到的一个例子。没看懂回调函数到底有... 为什么说气是血之帅,血是气之母 php回调函数是什么样子的?靠什么原理运行? PHP回调函数的几种用法 气血和,和气血,用来调理气血间的关系 分期乐逾期分期乐逾期多少天上征信?五号还款,工资十五号才发。_百度问一问 PHP回调函数到底是个啥 新手刚学PHP 对于回调函数不太理解 求教大伙一下! 写话,清蒸鲈鱼作文200字? 请问,如何种大蒜 职业选手阿泰的游戏账号遭遇封禁,大家觉得阿泰真的有违规还是被误封? 在农村种植野菜,要怎样去寻找销路? 香薷的栽培技术 种空心菜的方法 360全景拍摄制作用什么相机好? 360全景拍摄设备都有哪些啊? 360度全景拍摄器材需要什么设备? 360相机晚上可以拍烟花吗 wunder360相机好用吗?业余拍摄者能操控吗? 苹果8手机售后服务一般要多久 坚守岗位的朋友圈怎么发 对节假日还在一线工作的人,该用什么样的话来称赞 坚守岗位的优美句子 军人坚守岗位的优美句子 劳动节,该如何向身边坚守岗位的人说声谢谢呢? 关于坚守的优美句子 赞美坚守的经典句子