在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 进程锁定问题分析研究
Nov 24 PHP
php模拟socket一次连接,多次发送数据的实现代码
Jul 26 PHP
PHP实现把文本中的URL转换为链接的auolink()函数分享
Jul 29 PHP
php通过文件流方式复制文件的方法
Mar 13 PHP
typecho插件编写教程(四):插件挂载
May 28 PHP
php实现将上传word文件转为html的方法
Jun 03 PHP
php自定义函数实现JS的escape的方法示例
Jul 07 PHP
php操纵mysqli数据库的实现方法
Sep 18 PHP
PHP基于mssql扩展远程连接MSSQL的简单实现方法
Oct 08 PHP
PHP策略模式定义与用法示例
Jul 27 PHP
Smarty模板类内部原理实例分析
Jul 03 PHP
php双向队列实例讲解
Nov 17 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 日期和时间的处理-郑阿奇(续)
2011/07/04 PHP
PHP实现Javascript中的escape及unescape函数代码分享
2015/02/10 PHP
php 数组字符串搜索array_search技巧
2016/07/05 PHP
php修改数组键名的方法示例
2017/04/15 PHP
PHP 中TP5 Request 请求对象的实例详解
2017/07/31 PHP
jquery 图片截取工具jquery.imagecropper.js
2010/04/09 Javascript
浅谈JavaScript函数参数的可修改性问题
2013/12/05 Javascript
用json方式实现在 js 中建立一个map
2014/05/02 Javascript
分享十五款 jQuery 社交网络分享插件
2015/05/16 Javascript
JS简单模拟触发按钮点击功能的方法
2015/11/30 Javascript
深入php面向对象、模式与实践
2016/02/16 Javascript
基于JS实现textarea中获取动态剩余字数的方法
2016/05/25 Javascript
JavaScript中removeChild 方法开发示例代码
2016/08/15 Javascript
jQuery实现智能判断固定导航条或侧边栏的方法
2016/09/04 Javascript
JavaScript每天必学之基础知识
2016/09/17 Javascript
react native仿微信PopupWindow效果的实例代码
2017/08/07 Javascript
jQuery+ajax读取json数据并按照价格排序示例
2018/03/28 jQuery
解决vue中使用proxy配置不同端口和ip接口问题
2019/08/14 Javascript
解决vue-router 二级导航默认选中某一选项的问题
2019/11/01 Javascript
JS实现页面数据懒加载
2020/02/13 Javascript
[05:17]DOTA2誓师:今天我们在这里 明天TI4等我!
2014/03/26 DOTA
[03:08]TI9战队档案 - Vici Gaming
2019/08/20 DOTA
Python中的错误和异常处理简单操作示例【try-except用法】
2017/07/25 Python
python pandas 对时间序列文件处理的实例
2018/06/22 Python
利用Python如何生成便签图片详解
2018/07/09 Python
python爬取cnvd漏洞库信息的实例
2019/02/14 Python
详解Python读取yaml文件多层菜单
2019/03/23 Python
如何使用Python自动生成报表并以邮件发送
2020/10/15 Python
python 发送get请求接口详解
2020/11/17 Python
Python面试题:Python里面如何生成随机数
2015/03/12 面试题
幼儿园亲子活动方案
2014/01/29 职场文书
员工拓展培训方案
2014/02/15 职场文书
应届本科毕业生求职信
2014/07/23 职场文书
领导干部民主生活会自我剖析材料范文
2014/09/20 职场文书
2014年科研工作总结
2014/12/03 职场文书
Python爬虫之爬取二手房信息
2021/04/27 Python