在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 相关文章推荐
phpMyAdmin 链接表的附加功能尚未激活的问题
Aug 01 PHP
PHP函数之error_reporting(E_ALL ^ E_NOTICE)详细说明
Jul 01 PHP
PHP中__get()和__set()的用法实例详解
Jun 04 PHP
PHP关于htmlspecialchars、strip_tags、addslashes的解释
Jul 04 PHP
php可应用于面包屑导航的递归寻找家谱树实现方法
Feb 02 PHP
PHP生成随机字符串(3种方法)
Sep 25 PHP
基于OpenCart 开发支付宝,财付通,微信支付参数错误问题
Oct 01 PHP
PHP+jQuery翻板抽奖功能实现
Oct 19 PHP
PHP实现随机生成水印图片功能
Mar 22 PHP
php封装单文件上传到数据库(路径)
Oct 15 PHP
laravel框架分组控制器和分组路由实现方法示例
Jan 25 PHP
PHP数组基本用法与知识点总结
Jun 02 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
咖啡常见的种类
2021/03/03 新手入门
截获网站title标签之家内容的例子
2006/10/09 PHP
PHP 彩色文字实现代码
2009/06/29 PHP
php进程间通讯实例分析
2016/07/11 PHP
javascript基础的动画教程,直观易懂
2007/01/10 Javascript
jQuery 相关控件的事件操作分解
2009/08/03 Javascript
获取div编辑框,textarea,input text的光标位置 兼容IE,FF和Chrome的方法介绍
2012/11/08 Javascript
缓动函数requestAnimationFrame 更好的实现浏览器经动画
2012/12/07 Javascript
js清理Word格式示例代码
2014/02/13 Javascript
原生javascript实现Tab选项卡切换功能
2015/01/12 Javascript
AngularJS 最常用的功能汇总
2016/02/17 Javascript
jquery Deferred 快速解决异步回调的问题
2016/04/05 Javascript
jQuery插件开发汇总
2016/05/15 Javascript
全面了解JS中的匿名函数
2016/06/29 Javascript
vue.js编译时给生成的文件增加版本号
2018/09/17 Javascript
深入Node TCP模块的理解
2019/03/13 Javascript
layer父页获取弹出层输入框里面的值方法
2019/09/02 Javascript
vue中defineProperty和Proxy的区别详解
2020/11/30 Vue.js
Swift中的协议(protocol)学习教程
2016/07/08 Python
Python将一个CSV文件里的数据追加到另一个CSV文件的方法
2018/07/04 Python
python代码过长的换行方法
2018/07/19 Python
详解Python locals()的陷阱
2019/03/26 Python
详解Python字符串切片
2019/05/20 Python
Python 离线工作环境搭建的方法步骤
2019/07/29 Python
python实现批量文件重命名
2019/10/31 Python
python 用opencv实现霍夫线变换
2020/11/27 Python
英国最大的网上药品商店:Chemist Direct
2017/12/16 全球购物
西安启天科技有限公司网络工程师面试题笔试题
2016/06/12 面试题
生物化学研究助理员求职信
2013/10/09 职场文书
人力资源管理专业毕业生推荐信
2013/11/07 职场文书
怎么写好自荐书
2014/03/02 职场文书
人与自然观后感
2015/06/16 职场文书
干部外出学习心得体会
2016/01/18 职场文书
《乌鸦喝水》教学反思
2016/02/19 职场文书
MySQL 8.0 之不可见列的基本操作
2021/05/20 MySQL
纯html+css实现打字效果
2021/08/02 HTML / CSS