在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 相关文章推荐
解析Linux下Varnish缓存的配置优化
Jun 20 PHP
php中读写文件与读写数据库的效率比较分享
Oct 19 PHP
php获取远程图片体积大小的实例
Nov 12 PHP
PHP中常用的字符串格式化函数总结
Nov 19 PHP
php判断当前用户已在别处登录的方法
Jan 06 PHP
php metaphone()函数及php localeconv() 函数实例解析
May 15 PHP
php实现带读写分离功能的MySQL类完整实例
Jul 28 PHP
浅谈php和js中json的编码和解码
Oct 24 PHP
php实现xml转换数组的方法示例
Feb 03 PHP
ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解
Apr 02 PHP
mysqli扩展无法在PHP7下升级问题的解决
Sep 10 PHP
PHP学习记录之常用的魔术常量详解
Dec 12 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 cookie 登录验证示例代码
2009/03/16 PHP
PHP 正则判断中文UTF-8或GBK的思路及具体实现
2013/11/26 PHP
thinkPHP自定义类实现方法详解
2016/11/30 PHP
PHP 多任务秒级定时器的实现方法
2018/05/13 PHP
PHP7 mongoDB扩展使用的方法分享
2019/05/02 PHP
laravel model 两表联查示例
2019/10/24 PHP
Javascript常用运算符(Operators)-javascript基础教程
2007/12/14 Javascript
基于jquery实现导航菜单高亮显示(两种方法)
2015/08/23 Javascript
详解AngularJS中自定义过滤器
2015/12/28 Javascript
javascript函数自动执行常用方法汇总
2016/03/28 Javascript
JS控制伪元素的方法汇总
2016/04/06 Javascript
JavaScript操作 url 中 search 部分方法函数
2016/06/15 Javascript
WebSocket+node.js创建即时通信的Web聊天服务器
2016/08/08 Javascript
微信小程序 在Chrome浏览器上运行以及WebStorm的使用
2016/09/27 Javascript
Javascript的this用法
2017/01/16 Javascript
基于JavaScript实现焦点图轮播效果
2017/03/27 Javascript
浅析Angular2子模块以及异步加载
2017/04/24 Javascript
AngularJS 购物车全选/取消全选功能的实现方法
2017/08/14 Javascript
对于input 框限定输入值为浮点型的js代码
2017/09/25 Javascript
详解Vue组件之作用域插槽
2018/11/22 Javascript
js中Generator函数的深入讲解
2019/04/07 Javascript
a标签调用js的方法总结
2019/09/05 Javascript
vue-父子组件和ref实例详解
2019/11/10 Javascript
windows10系统中安装python3.x+scrapy教程
2016/11/08 Python
Django框架模板介绍
2019/01/15 Python
python如何以表格形式打印输出的方法示例
2019/06/21 Python
解决Python正则表达式匹配反斜杠''\''问题
2019/07/17 Python
从零实现一个自定义html5播放器的示例代码
2017/08/01 HTML / CSS
Homestay中文官网:全球寄宿家庭
2018/10/18 全球购物
如何删除一个表里面的重复行
2013/07/13 面试题
党的群众路线教育实践活动个人对照检查剖析材料
2014/09/23 职场文书
党员民主评议自我评价
2014/10/20 职场文书
逃课检讨书怎么写
2015/01/01 职场文书
护士个人年度总结范文
2015/02/13 职场文书
资深HR教你写好简历中的自我评价
2019/05/07 职场文书
python OpenCV学习笔记
2021/03/31 Python