在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 相关文章推荐
漂亮但不安全的CTB
Oct 09 PHP
如何将一个表单同时提交到两个地方处理
Oct 09 PHP
PHP中文件读、写、删的操作(PHP中对文件和目录操作)
Mar 06 PHP
destoon复制新模块的方法
Jun 21 PHP
PHP+MySQL统计该库中每个表的记录数并按递减顺序排列的方法
Feb 15 PHP
php中的登陆login实例代码
Jun 20 PHP
浅谈php中fopen不能创建中文文件名文件的问题
Feb 06 PHP
使用Zttp简化Guzzle 调用
Jul 02 PHP
简单实现php上传文件功能
Sep 21 PHP
PHP封装的page分页类定义与用法完整示例
Dec 24 PHP
php成功操作redis cluster集群的实例教程
Jan 13 PHP
laravel通过a标签从视图向控制器实现传值
Oct 15 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面向对象学习之parent::关键字
2017/01/18 PHP
CI(CodeIgniter)框架实现图片上传的方法
2017/03/24 PHP
Laravel 5.5 的自定义验证对象/类示例代码详解
2017/08/29 PHP
PHP优化之批量操作MySQL实例分析
2020/04/23 PHP
document.all还是document.getElementsByName?
2006/07/21 Javascript
用js实现随机返回数组的一个元素
2007/08/13 Javascript
javascript 导出数据到Excel(处理table中的元素)
2009/12/18 Javascript
Javascript 中的 call 和 apply使用介绍
2012/02/22 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
Jquery修改image的src属性,图片不加载问题的解决方法
2016/05/17 Javascript
node.js-v6新版安装具体步骤(分享)
2017/09/06 Javascript
layui实现form表单同时提交数据和文件的代码
2019/10/25 Javascript
python实现迭代法求方程组的根过程解析
2019/11/25 Javascript
python中wx将图标显示在右下角的脚本代码
2013/03/08 Python
Python运算符重载用法实例分析
2015/06/01 Python
详解Python中contextlib上下文管理模块的用法
2016/06/28 Python
python 实现图片旋转 上下左右 180度旋转的示例
2019/01/24 Python
python实现扫描ip地址的小程序
2019/04/16 Python
在Python中使用MongoEngine操作数据库教程实例
2019/12/03 Python
使用keras根据层名称来初始化网络
2020/05/21 Python
python 绘制国旗的示例
2020/09/27 Python
伦敦剧院门票:London Theatre Direct
2018/11/21 全球购物
eBay比利时购物网站:eBay.be
2019/08/09 全球购物
澳洲Chemist Direct药房中文网:澳洲大型线上直邮药房
2019/11/04 全球购物
培训专员岗位职责
2014/02/26 职场文书
市场营销专业大学生职业生涯规划文
2014/03/06 职场文书
单位工程竣工验收方案
2014/03/16 职场文书
公路局群众路线教育实践活动第一阶段工作汇报
2014/10/25 职场文书
实习介绍信模板
2015/01/30 职场文书
结婚喜宴祝酒词
2015/08/10 职场文书
如何用python识别滑块验证码中的缺口
2021/04/01 Python
python绘制箱型图
2021/04/27 Python
mongodb数据库迁移变更的解决方案
2021/09/04 MongoDB
一文了解JavaScript用Element Traversal新属性遍历子元素
2021/11/27 Javascript
请求模块urllib之PYTHON爬虫的基本使用
2022/04/08 Python
vue中data里面的数据相互使用方式
2022/06/05 Vue.js