php面向对象视频笔记之第六章(反射机制与动态代理)

1、反射机制与动态代理
php的Reflection反射机制
 php5添加了一项新的功能:Reflection。这个功能使得程序员可以reflection class,interfacce,function,

method...。通过php代码,就可以得到某类/方法等的所有信息,并且可以和它交互。


 反射机制的应用:
   动态代理:也叫委托模式,在委托模式中,有两个对象参与处理同个请求,接受请求的对象将请求委托给另一
个对象来处理。
   插件系统:利用反射机制自动获取插件列表以及其它的相关信息。

ReflectionFunction应用示例如下即运行结果:

<?php

/**
  测试函数注释
*/
function test(){
  //code
  echo '我是一个测试的函数.<br />';
}

test();

$ref_fun = new ReflectionFunction('test');//参数即函数名

echo $ref_fun->getDocComment();//函数注释
echo '<br />定义在文件:',$ref_fun->getFileName();//函数定义所在的文件
echo '<br />代码开始行:',$ref_fun->getStartLine();//开始行
echo '<br />代码结束行:',$ref_fun->getEndLine();//结束行

try{
  new ReflectionFunction('test1');
}catch(ReflectionException $e){
  echo '<br />',$e->getMessage();
}


php用反射机制实现动态代理

ref.php

<?php
class A{
   function t1(){
      echo '我是一个不带参数的方法t1<br />';
   }
   function t2($str){
      echo '我是一个带一个参数的方法t2,参数是:',$str,'<br/ >';
   }
   private function t3(){
      
   }
   static function t4(){
      echo '我是一个静态方法<br />';
   }
}

$a = new A();

$ref_cls = new ReflectionClass('A');//参数可是类名,也可是类的实例如new ReflectionClass($a);
//获取类中的所有方法
$class_all_methods = $ref_cls->getMethods();
print_r($class_all_methods);
echo '<br />以下是判断类中是否有某个方法的结果.<br />';
//判断类中是否有某个方法 hasMethod 返回布尔值
var_dump($ref_cls->hasMethod('t1'));//bool true
echo '<br />';
var_dump($ref_cls->hasMethod('t')); //bool false
echo '<hr />';
echo '以下是判断类中某个方法权限和调用运行的结果.<br />';
//判断方法的修饰符 public protected private static
//判断方式:is+修饰符 返回的是布尔值
//判断之前要获取类中的方法
$ref_method = $ref_cls->getMethod('t1');//参数是方法名

var_dump($ref_method->isPublic());//是否为公开方法 bool true
echo '<br />';
//执行方法
//静态方法调用 invoke(null,参数);
//普通方法调用 invoke(实例对象,参数);
//私有方法不能被invoke调用。
if($ref_method->isPublic() && !$ref_method->isAbstract()){//是公开且非抽象。
   if($ref_method->isStatic()){
      $ref_method->invoke(null);
   }else{
      $ref_method->invoke($a);
   }
}
//获取类中的方法的反射类(跟上面的方法作用一样)
$ref_method = new ReflectionMethod('A','t3');//类名+方法名.
var_dump($ref_method->isPublic());//是否为公开方法 bool false
echo '<br />';
$ref_method = new ReflectionMethod('A','t2');
var_dump($ref_method->isStatic());//是否为静态方法 bool true
echo '<br />';
if($ref_method->isPublic() && !$ref_method->isAbstract()){//是公开且非抽象。
   if($ref_method->isStatic()){
      $ref_method->invoke(null,'yi');
   }else{
      $ref_method->invoke($a,'yi');
   }
}

运行结果:


dynamic.php

<?php
class A{
  function showInfoA(){
     echo 'function "showInfoA()" of Class A.<br />';
  }
}
class C{
  function showInfoC(){
     echo 'function "showInfoC()" of Class C.<br />';
  }
}
class B{
  private $obj;

  function __construct(){
    //$this->obj = new A();//添加单个数组元素
  }
  
   function addObj($obj){ //动态添加对象数组
     $this->obj[] = $obj; //依次后补数组元素
	 print_r($this->obj);//查看数组元素
	 echo '<hr />';
   }
  
  function __call($name,$args){
	foreach($this->obj as $v){//遍历数组元素
	  $ref_cls = new ReflectionClass($v);//反射出该对象所在类名
	 if($ref_cls->hasMethod($name)){//判断该类是否有该方法
	  $ref_method = $ref_cls->getMethod($name);
      if($ref_method->isPublic() && !$ref_method->isAbstract())
	  {
	     if($ref_method->isStatic()){
		   $ref_method->invoke(null);
		 }else{
		   $ref_method->invoke($v);
		 }  
	  }
	 }
	}
	  /*添加单个对象的情况
    $ref_cls = new ReflectionClass($this->obj);
	if($ref_cls->hasMethod($name)){
	  $ref_method = $ref_cls->getMethod($name);
      if($ref_method->isPublic() && !$ref_method->isAbstract())
	  {
	     if($ref_method->isStatic()){
		   $ref_method->invoke(null);
		 }else{
		   $ref_method->invoke($this->obj);
		 }  
	  }
	}*/
  }
}

$b = new B();
$b->addObj(new A());
$b->addObj(new C());
$b->showInfoA();
$b->showInfoC();
运行结果:


插件雏形示例:

plugin.php:

<?php

interface Plugin{
   function showMenu();
}

class MyPlugin implements Plugin{
   //获取插件菜单
   function showMenu(){
      $menu = array(
	     array(
		   'name' => 'My_menu1',
		   'link' => 'index.php?act=my_link1'
	     ),
		 array(
		   'name' => 'My_menu2',
		   'link' => 'index.php?act=my_link2' 	 
		 )	 
	  );

		 //print_r($menu);
		 return $menu;
   }
}

class YourPlugin implements Plugin{
   //获取插件菜单
   function showMenu(){
      $menu = array(
	     array(
		   'name' => 'Your_menu1',
		   'link' => 'index.php?act=your_link1'
	     ),
	     array(
		   'name' => 'Your_menu2',
		   'link' => 'index.php?act=your_link2' 
		 )		 
	  );

		 //print_r($menu);
		 return $menu;
   }
}


demo.php:

<?php
//echo __DIR__; 当前目录
include_once __DIR__.'/plugin.php';//在当前目录加上此文件

function get_plugin_menus(){
   $all_class = get_declared_classes();
   //print_r($all_class);
   $menu = $menus = array();
   foreach($all_class as $cls){
     $ref_cls = new ReflectionClass($cls);
	 //判断这个类是否实现了某个接口
	 if($ref_cls->implementsInterface('Plugin')){
	    //echo $cls,'<br />';
		if($ref_cls->hasMethod('showMenu')){
		  $ref_method = $ref_cls->getMethod('showMenu');
		  if($ref_method->isPublic() && !$ref_method->isAbstract()){
		    if($ref_method->isStatic()){
			   $menu = $ref_method->invoke(null);
			}else{
               //通过反射类获取类的一个实例
			   //$menu = $ref_method->invoke(new $cls());
			   $instance = $ref_cls->newInstance();
			   $menu = $ref_method->invoke($instance);
			}
			//合并菜单
			$menus = array_merge($menus,$menu);
		  }
		}
	 }
   }
   //print_r($menus);
   return $menus;
}

$menu_list = get_plugin_menus();
foreach($menu_list as $menu){
  echo '<a href="'.$menu['link'].'">'.$menu['name'].'</a><br />';//菜单超链接
}
运行结果:





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值