在PHP中使用反射技术的架构插件使用说明


Posted in PHP onMay 18, 2010

反射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'); 
} 
} 
[html] 
这种情况并不太合理,因为满足了接口的要求,为大量方法添加了不会用到的函数体,如果在API中有数百个方法,这样是行不通的。 
反射API提供了一种解决方法,使用get_declared_classes()函数取得当前加载的类,并检测哪个类实现了IPlugin"标记"的方法。 
在这里写了一个使用反射查找插件的方法 
[code] 
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);
PHP 相关文章推荐
多重?l件?合查?(一)
Oct 09 PHP
PHP_MySQL教程-第一天
Mar 18 PHP
php park、unpark、ord 函数使用方法(二进制流接口应用实例)
Oct 19 PHP
注册页面之前先验证用户名是否存在的php代码
Jul 14 PHP
php输出xml属性的方法
Mar 19 PHP
微信公众平台之快递查询功能用法实例
Apr 14 PHP
适合PHP初学者阅读的4本经典书籍
Sep 23 PHP
Yii框架弹出窗口组件CJuiDialog用法分析
Jan 07 PHP
PHP explode()函数用法讲解
Feb 15 PHP
PHP实现数组和对象的相互转换操作示例
Mar 20 PHP
Laravel5.1 框架数据库操作DB运行原生SQL的方法分析
Jan 07 PHP
PHP 写文本日志实现代码
May 18 #PHP
php 随机记录mysql rand()造成CPU 100%的解决办法
May 18 #PHP
PHP array_flip() 删除重复数组元素专用函数
May 16 #PHP
mysql下创建字段并设置主键的php代码
May 16 #PHP
php带密码功能并下载远程文件保存本地指定目录 修改加强版
May 16 #PHP
ezSQL PHP数据库操作类库
May 16 #PHP
php 提速工具eAccelerator 配置参数详解
May 16 #PHP
You might like
一篇有意思的技术文章php介绍篇
2010/10/26 PHP
PHP中替换换行符的几种方法小结
2012/10/15 PHP
php模拟ping命令(php exec函数的使用方法)
2013/10/25 PHP
php数组冒泡排序算法实例
2016/05/06 PHP
PHP配置ZendOpcache插件加速
2019/02/14 PHP
5 cool javascript apps
2007/03/24 Javascript
基于JQUERY的两个ListBox子项互相调整的实现代码
2011/05/07 Javascript
JavaScript实现拼音排序的方法
2012/11/20 Javascript
jQuery fadeTo方法调整图片的透明度使用介绍
2013/05/06 Javascript
让页面上两个div中的滚动条(滑块)同步运动示例
2013/08/07 Javascript
jquery实现人性化的有选择性禁用鼠标右键
2014/06/30 Javascript
微信js-sdk分享功能接口常用逻辑封装示例
2016/10/13 Javascript
JavaScript中Array对象用法实例总结
2016/11/29 Javascript
Vue 中axios配置实例详解
2018/07/27 Javascript
javascript数据结构之多叉树经典操作示例【创建、添加、遍历、移除等】
2018/08/01 Javascript
使用electron实现百度网盘悬浮窗口功能的示例代码
2018/10/24 Javascript
[50:15]VP vs Mineski 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
详解python实现线程安全的单例模式
2018/03/05 Python
对Python中数组的几种使用方法总结
2018/06/28 Python
Python实现矩阵相乘的三种方法小结
2018/07/26 Python
详解python的四种内置数据结构
2019/03/19 Python
Python3enumrate和range对比及示例详解
2019/07/13 Python
django 邮件发送模块smtp使用详解
2019/07/22 Python
Python中*args和**kwargs的区别详解
2019/09/17 Python
简单了解Python3 bytes和str类型的区别和联系
2019/12/19 Python
python根据完整路径获得盘名/路径名/文件名/文件扩展名的方法
2020/04/22 Python
python实时监控logstash日志代码
2020/04/27 Python
美国校园市场:OCM
2017/06/08 全球购物
护士个人简历自荐信
2013/10/18 职场文书
关于母亲节的感言
2014/02/04 职场文书
纪念一二九运动演讲稿
2014/09/16 职场文书
党的群众路线教育实践活动总结大会主持词
2014/10/30 职场文书
保研专家推荐信范文
2015/03/25 职场文书
增值税发票丢失证明
2015/06/19 职场文书
2019年12月24日平安夜祝福语集锦
2019/12/24 职场文书
Java8利用Stream对列表进行去除重复的方法详解
2022/04/14 Java/Android