在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 相关文章推荐
建立文件交换功能的脚本(一)
Oct 09 PHP
E路文章系统PHP
Dec 11 PHP
一个数据采集类
Feb 14 PHP
PHP和XSS跨站攻击的防范
Apr 17 PHP
PHP 自定义错误处理函数的使用详解
May 10 PHP
ThinkPHP视图查询详解
Jun 30 PHP
微信公众平台网页授权获取用户基本信息中授权回调域名设置的变动
Oct 21 PHP
php可应用于面包屑导航的迭代寻找家谱树实现方法
Feb 02 PHP
PHP入门教程之字符串处理技巧总结(转换,过滤,解析,查找,截取,替换等)
Sep 11 PHP
PHP快速排序算法实现的原理及代码详解
Apr 03 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
Dec 30 PHP
TP5框架页面跳转样式操作示例
Apr 05 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
什么是短波收听SWL
2021/03/01 无线电
php支持断点续传、分块下载的类
2016/05/02 PHP
php实现的中秋博饼游戏之绘制骰子图案功能示例
2017/11/06 PHP
用javascript实现的图片马赛克后显示并切换加文字功能
2007/04/21 Javascript
JQuery扩展插件Validate 3通过参数设置错误信息
2011/09/05 Javascript
javascript中call和apply方法浅谈
2013/09/27 Javascript
jQuery实现当按下回车键时绑定点击事件
2014/01/28 Javascript
jquery实现侧边弹出的垂直导航
2014/12/09 Javascript
Laravel中常见的错误与解决方法小结
2016/08/30 Javascript
jQuery特殊符号转义的实现
2016/11/30 Javascript
非常优秀的JS图片轮播插件Swiper的用法
2017/01/03 Javascript
vue中mint-ui的使用方法
2018/04/04 Javascript
浅谈使用mpvue开发小程序需要注意和了解的知识点
2018/05/23 Javascript
vuejs router history 配置到iis的方法
2018/09/20 Javascript
基于vue.js组件实现分页效果
2018/12/29 Javascript
[01:03]悬念揭晓 11月26日DOTA2完美盛典不见不散
2017/11/23 DOTA
[01:54]TI珍贵瞬间系列(三):翻盘
2020/08/28 DOTA
Python实现从订阅源下载图片的方法
2015/03/11 Python
python 内置函数filter
2017/06/01 Python
Windows下anaconda安装第三方包的方法小结(tensorflow、gensim为例)
2018/04/05 Python
详解Django-restframework 之频率源码分析
2019/02/27 Python
OpenCV 模板匹配
2019/07/10 Python
tensorflow入门:TFRecordDataset变长数据的batch读取详解
2020/01/20 Python
python热力图实现简单方法
2021/01/29 Python
AmazeUI 输入框组的示例代码
2020/08/14 HTML / CSS
美国汽车交易网站:Edmunds
2016/08/17 全球购物
澳大利亚买卖正宗二手奢侈品交易平台:Luxe.It.Fwd
2019/10/16 全球购物
美国最大的烧烤架和户外生活用品专业零售商:Barbeques Galore
2021/01/09 全球购物
匡威俄罗斯官网:Converse俄罗斯
2020/05/09 全球购物
澳大利亚头发和美容产品购物网站:OZ Hair & Beauty
2020/03/27 全球购物
机电一体化专业应届生求职信
2013/11/27 职场文书
车辆工程专业求职信
2014/06/14 职场文书
小学感恩主题班会
2015/08/12 职场文书
教你如何用Python实现人脸识别(含源代码)
2021/06/23 Python
一定要知道的 25 个 Vue 技巧
2021/11/02 Vue.js
python​格式化字符串
2022/04/20 Python