在PHP中使用反射技术的架构插件使用说明

yipeiwu_com5年前PHP代码库
反射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 中文字符入库或显示乱码问题的解决方法

大家以后在编写过程中, 一定要记得定义字符类型。mysql_query("set names 'gbk'") 解决的方法就这么简单。 今天做了一个数据库查询,放出代码。 复制代码 代码如...

详解WordPress中调用评论模板和循环输出评论的PHP函数

comments_template comments_template 函数是一个调用评论模板的函数,使用起来很简单,与get_header()等函数一样,是一个include文件类函数...

php获取QQ头像并显示的方法

本文实例讲述了php获取QQ头像并显示的方法。分享给大家供大家参考。具体分析如下: 最近看到博客留言的头像有点别扭,因为游客的头像都是同一个头像,看着不是很舒服。虽然现在绝大多数的主题集...

php 修改、增加xml结点属性的实现代码

php 修改 增加xml结点属性的代码,供大家学习参考。php修改xml结点属性,增加xml结点属性的代码,有需要的朋友,参考下。 1、xml文件 复制代码 代码如下:<?xml...

PHP 单引号与双引号的区别

1、定义字符串   在PHP中,字符串的定义可以使用单引号,也可以使用双引号。但是必须使用同一种单或双引号来定义字符串,如:‘Hello"和“Hello'为非法的字符串定义。    定义...