在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+mysql 采用ajax技术的 省 市 地 3级联动无刷新菜单 源码
Dec 16 PHP
php桌面中心(二) 数据库写入
Mar 11 PHP
不错的一篇面向对象的PHP开发模式(简写版)
Mar 15 PHP
[原创]效率较高的php下读取文本文件的代码
Jul 02 PHP
PHP写UltraEdit插件脚本实现方法
Dec 26 PHP
php读取目录所有文件信息dir示例
Mar 18 PHP
PHP使用feof()函数读文件的方法
Nov 07 PHP
php实现复制移动文件的方法
Jul 29 PHP
老司机传授Ubuntu下Apache+PHP+MySQL环境搭建攻略
Mar 20 PHP
php实现base64图片上传方式实例代码
Feb 22 PHP
php无限级分类实现评论及回复功能
Feb 18 PHP
解决Laravel 不能创建 migration 的问题
Oct 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
第七节 类的静态成员 [7]
2006/10/09 PHP
PHP应用JSON技巧讲解
2013/02/03 PHP
ini_set的用法介绍
2014/01/07 PHP
PHP中COOKIES使用示例
2015/07/26 PHP
ThinkPHP框架搭建及常见问题(XAMPP安装失败、Apache/MySQL启动失败)
2016/04/15 PHP
PHP字典树(Trie树)定义与实现方法示例
2017/10/09 PHP
Nigma vs Alliance BO5 第四场2.14
2021/03/10 DOTA
修复ie8&chrome下window的resize事件多次执行
2011/10/20 Javascript
jQuery.extend 函数详解
2012/02/03 Javascript
jquery弹出框的用法示例(2)
2013/08/26 Javascript
Nodejs学习笔记之入门篇
2015/04/16 NodeJs
JQUERY表单暂存功能插件分享
2016/02/23 Javascript
第一次接触神奇的Bootstrap
2016/10/14 Javascript
jQuery层级选择器实例代码
2017/02/06 Javascript
angular中ui calendar的一些使用心得(推荐)
2017/11/03 Javascript
vue 全选与反选的实现方法(无Bug 新手看过来)
2018/02/09 Javascript
vue-cli开发环境实现跨域请求的方法
2018/04/07 Javascript
javascript二维数组和对象的深拷贝与浅拷贝实例分析
2019/10/26 Javascript
[02:42]决战东方!DOTA2亚洲邀请赛重启荣耀之争
2017/03/17 DOTA
[52:37]完美世界DOTA2联赛循环赛 Forest vs DM BO2第一场 10.29
2020/10/29 DOTA
Python里disconnect UDP套接字的方法
2015/04/23 Python
Python中的变量和作用域详解
2016/07/13 Python
Python 转义字符详细介绍
2017/03/21 Python
简单谈谈Python的pycurl模块
2018/04/07 Python
对Pandas MultiIndex(多重索引)详解
2018/11/16 Python
Django Rest framework认证组件详细用法
2019/07/25 Python
PyTorch实现AlexNet示例
2020/01/14 Python
python绕过图片滑动验证码实现爬取PTA所有题目功能 附源码
2021/01/06 Python
JOSEPH官网:英国奢侈时尚品牌
2018/01/31 全球购物
德国家具、照明、家居用品网上商店:Wayfair.de
2020/02/13 全球购物
初中考试作弊检讨书
2014/02/01 职场文书
电脑专业个人求职信范文
2014/02/04 职场文书
共产党员批评与自我批评
2014/10/15 职场文书
酒会开场白大全
2015/06/01 职场文书
使用Springboot实现健身房管理系统
2021/07/01 Java/Android
app场景下uniapp的扫码记录
2022/07/23 Java/Android