• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

理解在PHP中使用反射技术的架构插件

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

 

  基于反射的插件架构实际上并没有归类为一种模式,因为它实际上不是一个模板,而是一糸列组合在一起的形成程序架构的概念。

反射API的插件方法是基于在运行时决定程序的功能来实现的,也就是说,它允许创建可选的接口方法,并在首次使用时检测到这部分接口方法,只有在插件中存在这部分接口的情况下,它们才会被用到.

 

假设拥有这样的接口

interface  IPlugin{
	
	function getMenuItems();
	function getArticles();
	function getSideBars();
	
}
class Someplugin implelents IPlugin{
     public function getMenuItems(){
//没有菜单项 
   return null;
 }
   public function getArticles(){ 
//没有任何文章
   return null;
 }
public function getSidBars(){
   //有侧边
return array("sidbarItem');
}
}
这种情况并不太合理,因为满足了接口的要求,为大量方法添加了不会用到的函数体,如果在API中有数百个方法,这样是行不通的。

反射API提供了一种解决方法,使用get_declared_classes()函数取得当前加载的类,并检测哪个类实现了IPlugin"标记"的方法。
在这里写了一个使用反射查找插件的方法
function findPlugins(){
 $plugins=array();
 foreach (get_declared_classes() as $class){
  $reflectionsClass=new ReflectionClass($class);
  if($reflectionsClass->implementsInterface('IPlugin')){
   $plugins[]=$reflectionsClass;
  }
 }
 return $plugins;
 
}
为了为了确定类是否实现了单个方法,可以使用REfectionClass类的hasMethod()方法。
确定用于菜单的类的成员
function computerMenu(){
 $menu=array();
 foreach (findPlugins() as $plugin){
  if($plugin->hasMethod('getMenuItems')){
   $reflectionMethod=$plugin->getMethod('getMenuItems');
   if($reflectionMethod->isStatic()){
    $items=$reflectionMethod->invoke(null);
    
   }else{
    $pluginInstance=$plugin->newInstance();
    $items=$reflectionMethod->invoke($pluginInstance);
   }
   $menu=array_merge($menu,$items);
  }
 }
 return $menu;
}
得到类的实例后,需要检测是否能够静态检测调用API方法,如果方法是静态的,只需要调用 invoke()函数,
如下 public mixed invoke(stdclass object,mixed args=null)
另一方面,如果方法不是静态的,需要取得插件的一个实例来调用这个方法,要从Refectionclass对象取得类的一个实例,
调用 它的newInstance()方法,然后再使用invoke()方法,返回实例传入就可以。
确定用于文章和侧边的类的成员

function computeArticles(){
 $articles=array();
 foreach (findPlugins() as $plugin){
  if($plugin->hasMethod('getArticles')){
   $reflectionMethod=$plugin->getMethod('getArticles');
   if($reflectionMethod->isStatic()){
    $items=$reflectionMethod->invoke(null);
    
   }else{
    $pluginInstance=$plugin->newInstance();
    $items=$reflectionMethod->invoke($pluginInstance);
   }
   $articles=array_merge($articles,$items);
  }
 }
 return $articles;
 
}
function computeSidebars(){
 $sidebars=array();
 foreach (findPlugins() as $plugin){
  if($plugin->hasMethod('getSidebars')){
   $reflectionMethod=$plugin->getMethod('getSidebars');
   if($reflectionMethod->isStatic()){
    $items=$reflectionMethod->invoke(null);
    
   }else{
    $pluginInstance=$plugin->newInstance();
    $items=$reflectionMethod->invoke($pluginInstance);
   }
   $sidebars=array_merge($sidebars,$items);
  }
 }
 return $sidebars;
}
创建一个实现了可选特性的反射式插件
class MyCoolPlugin implements IPlugin{
 public static function getName(){return 'MyCoolPlugin';}
 public static function getMenuItems(){
  //菜单项的数字索引数组
  return array(array('description'=>'MyCoolPlugin','link'=>'/MyCoolPlugin'));
 }
 
 public static function getArticles(){
  //文章的数字索引数组
  return array(array('path'=>'/MyCoolPlugin','title'=>'This is a really cool article',
  'text'=>'This article is cool because...'));
 }
 public static function getSideBars(){
  //文章的侧边栏索引数组
  return array(array('sideBars'=>'/MyCoolPlugin'));
 }
}
最后只要这样就可以使用这样插件了:

$menu=computeArticles();
$sidebars=computeSidebars();
$articles=computeArticles();

print_r($menu);
print_r($sidebars);
print_r($articles);


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
PHP程序员最易犯10种错误发布时间:2022-07-10
下一篇:
用php生成静态html页面发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap