在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 相关文章推荐
php foreach、while性能比较
Oct 15 PHP
PHP 防恶意刷新实现代码
May 16 PHP
PHP安全性漫谈
Jun 28 PHP
PHP远程采集图片详细教程
Jul 01 PHP
PHP函数in_array()使用详解
Aug 20 PHP
Yii框架获取当前controlle和action对应id的方法
Dec 03 PHP
php文件扩展名判断及获取文件扩展名的N种方法
Sep 12 PHP
php+ajax实现无刷新的新闻留言系统
Dec 21 PHP
PHP错误机制知识汇总
Mar 24 PHP
php自定义函数实现统计中文字符串长度的方法小结
Apr 15 PHP
PHP实现json_decode不转义中文的方法
May 20 PHP
php和js实现根据子网掩码和ip计算子网功能示例
Nov 09 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 strlen mb_strlen计算中英文混排字符串长度
2009/07/10 PHP
PHP调用Twitter的RSS的实现代码
2010/03/10 PHP
php实现简单洗牌算法
2013/06/18 PHP
php判断手机访问还是电脑访问示例分享
2014/01/20 PHP
php中文繁体和简体相互转换的方法
2015/03/21 PHP
php cookie 详解使用实例
2016/11/03 PHP
jQuery 表格工具集
2010/04/25 Javascript
fancybox1.3.1 基于Jquery的插件在IE中图片显示问题
2010/10/01 Javascript
javaScript NameSpace 简单说明介绍
2013/07/18 Javascript
JavaScript实现按Ctrl键打开新页面
2014/09/04 Javascript
jQuery中show与hide方法用法示例
2016/09/16 Javascript
细数JavaScript 一个等号,两个等号,三个等号的区别
2016/10/09 Javascript
jQuery实现联动下拉列表查询框
2017/01/04 Javascript
react.js 翻页插件实例代码
2017/01/19 Javascript
nodejs学习笔记之路由
2017/03/27 NodeJs
vue组件传递对象中实现单向绑定的示例
2018/02/28 Javascript
微信小程序全局变量GLOBALDATA的定义和调用过程解析
2019/09/23 Javascript
微信小程序实现一张或多张图片上传(云开发)
2019/09/25 Javascript
ES6 Promise对象概念及用法实例详解
2019/10/15 Javascript
解决vue elementUI 使用el-select 时 change事件的触发问题
2020/11/17 Vue.js
python根据文件大小打log日志
2014/10/09 Python
用Python实现换行符转换的脚本的教程
2015/04/16 Python
Python实现读取文件最后n行的方法
2017/02/23 Python
详解Python函数可变参数定义及其参数传递方式
2017/08/02 Python
Python使用回溯法子集树模板解决迷宫问题示例
2017/09/01 Python
python 2.7 检测一个网页是否能正常访问的方法
2018/12/26 Python
VSCode Python开发环境配置的详细步骤
2019/02/22 Python
Python实现个人微信号自动监控告警的示例
2019/07/03 Python
CSS3实现曲线阴影和翘边阴影
2016/05/03 HTML / CSS
高中生期末评语
2014/01/28 职场文书
房地产开发项目建议书
2014/05/16 职场文书
公司演讲稿开场白
2014/08/25 职场文书
抄袭同学作业检讨书1000字
2014/11/20 职场文书
2015年九一八事变纪念日演讲稿
2015/03/19 职场文书
golang 接口嵌套实现复用的操作
2021/04/29 Golang
3050和2060哪个好 性能差多少 差距有多大 谁更有性价比
2022/06/17 数码科技