在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 相关文章推荐
笑谈配置,使用Smarty技术
Jan 04 PHP
php下用GD生成生成缩略图的两个选择和区别
Apr 17 PHP
php之Memcache学习笔记
Jun 17 PHP
关于PHP内存溢出问题的解决方法
Jun 25 PHP
php取整函数ceil,floo,round的用法及介绍
Aug 31 PHP
让PHP显示Facebook的粉丝数量方法
Jan 08 PHP
thinkphp常见路径用法分析
Dec 02 PHP
php算法实例分享
Jul 14 PHP
整理php防注入和XSS攻击通用过滤
Sep 13 PHP
ThinkPHP下表单令牌错误与解决方法分析
May 20 PHP
学习thinkphp5.0验证类使用方法
Nov 16 PHP
Laravel5.4框架使用socialite实现github登录的方法
Mar 20 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
浅析Apache中RewriteCond规则参数的详细介绍
2013/06/30 PHP
PHP return语句另类用法不止是在函数中
2014/09/17 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
firefox firebug中文入门教程 脚本之家新年特别版
2010/01/02 Javascript
jQuery之网页换肤实现代码
2011/04/30 Javascript
jQuery.prototype.init选择器构造函数源码思路分析
2013/02/05 Javascript
jquery获得页面元素的坐标值实现思路及代码
2013/04/15 Javascript
jQuery使用andSelf()来包含之前的选择集
2014/05/19 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
基于JavaScript实现div层跟随滚动条滑动
2016/01/12 Javascript
Angular开发者指南之入门介绍
2017/03/05 Javascript
微信小程序 首页制作简单实例
2017/04/07 Javascript
vue刷新和tab切换实例
2018/02/11 Javascript
layer插件实现在弹出层中弹出一警告提示并关闭弹出层的方法
2019/09/24 Javascript
element-ui点击查看大图的方法示例
2020/12/14 Javascript
Python生成数字图片代码分享
2017/10/31 Python
Django中redis的使用方法(包括安装、配置、启动)
2018/02/21 Python
Python requests模块实例用法
2019/02/11 Python
python设置环境变量的原因和方法
2019/06/24 Python
用Pytorch训练CNN(数据集MNIST,使用GPU的方法)
2019/08/19 Python
python实现tail -f 功能
2020/01/17 Python
python 使用多线程创建一个Buffer缓存器的实现思路
2020/07/02 Python
Django-Scrapy生成后端json接口的方法示例
2020/10/06 Python
Python和Bash结合在一起的方法
2020/11/13 Python
python基于pexpect库自动获取日志信息
2021/02/01 Python
CSS3的Flexbox布局的简明入门指南
2016/04/08 HTML / CSS
Myprotein比利时官方网站:欧洲第一运动营养品牌
2020/10/04 全球购物
限量版运动鞋和街头服饰:TheDrop
2020/09/06 全球购物
优秀经理事迹材料
2014/02/01 职场文书
工地安全检查制度
2014/02/04 职场文书
优秀的导游求职信范文
2014/04/06 职场文书
刑事上诉状(无罪)
2015/05/23 职场文书
创业计划书之奶茶店开店方案范本!
2019/08/06 职场文书
Nginx + consul + upsync 完成动态负载均衡的方法详解
2021/03/31 Servers
Django项目如何获得SSL证书与配置HTTPS
2021/04/30 Python
Windows10安装Apache2.4的方法步骤
2022/06/25 Servers