在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 MVC模式在网站架构中的实现分析
Mar 04 PHP
php smarty 二级分类代码和模版循环例子
Jun 16 PHP
从手册去理解分析PHP session机制
Jul 17 PHP
PHP隐形一句话后门,和ThinkPHP框架加密码程序(base64_decode)
Nov 02 PHP
php计算数组不为空元素个数的方法
Jan 27 PHP
destoon实现调用自增数字从1开始的方法
Aug 21 PHP
9个经典的PHP代码片段分享
Dec 18 PHP
php实现比较全的数据库操作类
Jun 18 PHP
深入理解PHP中的Streams工具
Jul 03 PHP
PHP中使用array函数新建一个数组
Nov 19 PHP
php使用file函数、fseek函数读取大文件效率对比分析
Nov 04 PHP
swoole和websocket简单聊天室开发
Nov 18 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
截获网站title标签之家内容的例子
2006/10/09 PHP
php获取301跳转URL简单实例
2013/12/16 PHP
PHP CURL获取返回值的方法
2014/05/04 PHP
thinkphp四种url访问方式详解
2014/11/28 PHP
如何使用php等比例缩放图片
2016/10/12 PHP
PHP实现的多维数组排序算法分析
2018/02/10 PHP
Centos7 Yum安装PHP7.2流程教程详解
2019/07/02 PHP
JQuery的ajax基础上的超强GridView展示
2009/09/18 Javascript
brook javascript框架介绍
2011/10/10 Javascript
javascript模拟select,jselect的方法实现
2012/11/08 Javascript
jQuery数据缓存功能的实现思路及简单模拟
2013/05/27 Javascript
jquery等待效果示例
2014/05/01 Javascript
jQuery Ajax File Upload实例源码
2016/12/12 Javascript
Vue + Webpack + Vue-loader学习教程之功能介绍篇
2017/03/14 Javascript
浅谈React高阶组件
2018/03/28 Javascript
解决使用layui对select append元素无效或者未及时更新的问题
2019/09/18 Javascript
JavaScript监听触摸事件代码实例
2019/12/30 Javascript
[02:46]2014DOTA2国际邀请赛 选手为你解读比赛MVP充满梦想
2014/07/09 DOTA
python 图片验证码代码分享
2012/07/04 Python
python+opencv轮廓检测代码解析
2018/01/05 Python
Pyqt实现无边框窗口拖动以及窗口大小改变
2018/04/19 Python
不管你的Python报什么错,用这个模块就能正常运行
2018/09/14 Python
python3连接kafka模块pykafka生产者简单封装代码
2019/12/23 Python
python实现打砖块游戏
2020/02/25 Python
Python面向对象程序设计之静态方法、类方法、属性方法原理与用法分析
2020/03/23 Python
用HTML5实现网站在windows8中贴靠的方法
2013/04/21 HTML / CSS
英国文胸专家:AmpleBosom.com
2018/02/06 全球购物
分别介绍一下Session Bean和Entity Bean
2015/03/13 面试题
如何掌握自荐信格式呢
2013/11/19 职场文书
坚定理想信念心得体会
2014/03/11 职场文书
含预算的公司户外活动方案
2014/08/16 职场文书
明确岗位职责
2015/02/14 职场文书
2015年业务工作总结范文
2015/04/10 职场文书
公司庆典主持词
2015/07/04 职场文书
pytorch 带batch的tensor类型图像显示操作
2021/05/20 Python
Python通用验证码识别OCR库ddddocr的安装使用教程
2022/07/07 Python