在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 相关文章推荐
第七节 类的静态成员 [7]
Oct 09 PHP
php与XML、XSLT、Mysql的结合运用实现代码
Nov 19 PHP
ThinkPHP关联模型操作实例分析
Sep 23 PHP
解析PHP中$_FILES的使用以及注意事项
Jul 05 PHP
php使用curl发送json格式数据实例
Dec 17 PHP
ThinkPHP入口文件设置及相关注意事项分析
Dec 05 PHP
php mysql 封装类实例代码
Sep 18 PHP
PHP GD库相关图像生成和处理函数小结
Sep 30 PHP
详解如何在云服务器上部署Laravel
Jun 30 PHP
Laravel + Elasticsearch 实现中文搜索的方法
Feb 02 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
Feb 22 PHP
PHP哈希表实现算法原理解析
Dec 11 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
Zend studio文件注释模板设置方法
2013/09/29 PHP
php实现有趣的人品测试程序实例
2015/06/08 PHP
浅谈PHP面向对象之访问者模式+组合模式
2017/05/22 PHP
Laravel框架控制器,视图及模型操作图文详解
2019/12/04 PHP
js中的escape及unescape函数的php实现代码
2007/09/04 Javascript
js 获取Listbox选择的值的代码
2010/04/15 Javascript
使用javascript控制cookie显示和隐藏背景图
2014/02/12 Javascript
JavaScript利用正则表达式去除日期中的-
2014/06/09 Javascript
iframe里的页面禁止右键事件的方法
2014/06/10 Javascript
jQuery获取动态生成的元素示例
2014/06/15 Javascript
JavaScript通过Date-Mask将日期转换成字符串的方法
2015/06/04 Javascript
JavaScript数组迭代器实例分析
2015/06/09 Javascript
Javascript中判断对象是否为空
2015/06/10 Javascript
JavaScript图片轮播代码分享
2015/07/31 Javascript
基于javascript实现简单计算器功能
2016/01/03 Javascript
Node.js静态文件服务器改进版
2016/01/10 Javascript
JavaScript数组合并的多种方法
2016/05/22 Javascript
AngularJS实现分页显示数据库信息
2016/07/01 Javascript
js实现延迟加载的几种方法
2017/04/24 Javascript
jQuery ajax仿Google自动提示SearchSuggess功能示例
2019/03/28 jQuery
新手如何快速理解js异步编程
2019/06/24 Javascript
解决Vue打包上线之后部分CSS不生效的问题
2019/11/12 Javascript
vue实现简单跑马灯效果
2020/05/25 Javascript
[02:16]DOTA2超级联赛专访Burning 逆袭需要抓住机会
2013/06/24 DOTA
[59:15]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第一场 11.20
2020/11/20 DOTA
用Python实现命令行闹钟脚本实例
2016/09/05 Python
python enumerate函数的使用方法总结
2017/11/15 Python
python切片的步进、添加、连接简单操作示例
2019/07/11 Python
Python中zip()函数的简单用法举例
2019/09/02 Python
意大利制造的男鞋和女鞋:SCAROSSO
2018/03/07 全球购物
生物技术毕业生自荐信
2013/10/23 职场文书
函授毕业生的自我鉴定
2013/11/26 职场文书
简历里的自我评价
2014/01/31 职场文书
2014国庆节国旗下演讲稿(精选版)
2014/09/26 职场文书
放飞理想主题班会
2015/08/14 职场文书
python index() 与 rindex() 方法的使用示例详解
2022/12/24 Python