在PHP中使用反射技術(shù)的架構(gòu)插件使用說明
更新時(shí)間:2010年05月18日 23:14:52 作者:
基于反射的插件架構(gòu)實(shí)際上并沒有歸類為一種模式,因?yàn)樗鼘?shí)際上不是一個(gè)模板,而是一糸列組合在一起的形成程序架構(gòu)的概念。
反射API的插件方法是基于在運(yùn)行時(shí)決定程序的功能來實(shí)現(xiàn)的,也就是說,它允許創(chuàng)建可選的接口方法,并在首次使用時(shí)檢測(cè)到這部分接口方法,只有在插件中存在這部分接口的情況下,它們才會(huì)被用到.
假設(shè)擁有這樣的接口
interface IPlugin{
function getMenuItems();
function getArticles();
function getSideBars();
}
class Someplugin implelents IPlugin{
public function getMenuItems(){
//沒有菜單項(xiàng)
return null;
}
public function getArticles(){ //沒有任何文章
return null;
}
public function getSidBars(){
//有側(cè)邊
return array("sidbarItem');
}
}
[html]
這種情況并不太合理,因?yàn)闈M足了接口的要求,為大量方法添加了不會(huì)用到的函數(shù)體,如果在API中有數(shù)百個(gè)方法,這樣是行不通的。
反射API提供了一種解決方法,使用get_declared_classes()函數(shù)取得當(dāng)前加載的類,并檢測(cè)哪個(gè)類實(shí)現(xiàn)了IPlugin"標(biāo)記"的方法。
在這里寫了一個(gè)使用反射查找插件的方法
[code]
function findPlugins(){
$plugins=array();
foreach (get_declared_classes() as $class){
$reflectionsClass=new ReflectionClass($class);
if($reflectionsClass->implementsInterface('IPlugin')){
$plugins[]=$reflectionsClass;
}
}
return $plugins;
}
為了為了確定類是否實(shí)現(xiàn)了單個(gè)方法,可以使用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;
}
得到類的實(shí)例后,需要檢測(cè)是否能夠靜態(tài)檢測(cè)調(diào)用API方法,如果方法是靜態(tài)的,只需要調(diào)用 invoke()函數(shù),
如下 public mixed invoke(stdclass object,mixed args=null)
另一方面,如果方法不是靜態(tài)的,需要取得插件的一個(gè)實(shí)例來調(diào)用這個(gè)方法,要從Refectionclass對(duì)象取得類的一個(gè)實(shí)例,
調(diào)用 它的newInstance()方法,然后再使用invoke()方法,返回實(shí)例傳入就可以。
確定用于文章和側(cè)邊的類的成員
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;
}
創(chuàng)建一個(gè)實(shí)現(xiàn)了可選特性的反射式插件
class MyCoolPlugin implements IPlugin{
public static function getName(){return 'MyCoolPlugin';}
public static function getMenuItems(){
//菜單項(xiàng)的數(shù)字索引數(shù)組
return array(array('description'=>'MyCoolPlugin','link'=>'/MyCoolPlugin'));
}
public static function getArticles(){
//文章的數(shù)字索引數(shù)組
return array(array('path'=>'/MyCoolPlugin','title'=>'This is a really cool article',
'text'=>'This article is cool because...'));
}
public static function getSideBars(){
//文章的側(cè)邊欄索引數(shù)組
return array(array('sideBars'=>'/MyCoolPlugin'));
}
}
最后只要這樣就可以使用這樣插件了:
$menu=computeArticles();
$sidebars=computeSidebars();
$articles=computeArticles();
print_r($menu);
print_r($sidebars);
print_r($articles);
假設(shè)擁有這樣的接口
復(fù)制代碼 代碼如下:
interface IPlugin{
function getMenuItems();
function getArticles();
function getSideBars();
}
class Someplugin implelents IPlugin{
public function getMenuItems(){
//沒有菜單項(xiàng)
return null;
}
public function getArticles(){ //沒有任何文章
return null;
}
public function getSidBars(){
//有側(cè)邊
return array("sidbarItem');
}
}
[html]
這種情況并不太合理,因?yàn)闈M足了接口的要求,為大量方法添加了不會(huì)用到的函數(shù)體,如果在API中有數(shù)百個(gè)方法,這樣是行不通的。
反射API提供了一種解決方法,使用get_declared_classes()函數(shù)取得當(dāng)前加載的類,并檢測(cè)哪個(gè)類實(shí)現(xiàn)了IPlugin"標(biāo)記"的方法。
在這里寫了一個(gè)使用反射查找插件的方法
[code]
function findPlugins(){
$plugins=array();
foreach (get_declared_classes() as $class){
$reflectionsClass=new ReflectionClass($class);
if($reflectionsClass->implementsInterface('IPlugin')){
$plugins[]=$reflectionsClass;
}
}
return $plugins;
}
為了為了確定類是否實(shí)現(xiàn)了單個(gè)方法,可以使用REfectionClass類的hasMethod()方法。
確定用于菜單的類的成員
復(fù)制代碼 代碼如下:
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;
}
得到類的實(shí)例后,需要檢測(cè)是否能夠靜態(tài)檢測(cè)調(diào)用API方法,如果方法是靜態(tài)的,只需要調(diào)用 invoke()函數(shù),
如下 public mixed invoke(stdclass object,mixed args=null)
另一方面,如果方法不是靜態(tài)的,需要取得插件的一個(gè)實(shí)例來調(diào)用這個(gè)方法,要從Refectionclass對(duì)象取得類的一個(gè)實(shí)例,
調(diào)用 它的newInstance()方法,然后再使用invoke()方法,返回實(shí)例傳入就可以。
確定用于文章和側(cè)邊的類的成員
復(fù)制代碼 代碼如下:
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;
}
創(chuàng)建一個(gè)實(shí)現(xiàn)了可選特性的反射式插件
復(fù)制代碼 代碼如下:
class MyCoolPlugin implements IPlugin{
public static function getName(){return 'MyCoolPlugin';}
public static function getMenuItems(){
//菜單項(xiàng)的數(shù)字索引數(shù)組
return array(array('description'=>'MyCoolPlugin','link'=>'/MyCoolPlugin'));
}
public static function getArticles(){
//文章的數(shù)字索引數(shù)組
return array(array('path'=>'/MyCoolPlugin','title'=>'This is a really cool article',
'text'=>'This article is cool because...'));
}
public static function getSideBars(){
//文章的側(cè)邊欄索引數(shù)組
return array(array('sideBars'=>'/MyCoolPlugin'));
}
}
最后只要這樣就可以使用這樣插件了:
復(fù)制代碼 代碼如下:
$menu=computeArticles();
$sidebars=computeSidebars();
$articles=computeArticles();
print_r($menu);
print_r($sidebars);
print_r($articles);
您可能感興趣的文章:
- PHP的反射類ReflectionClass、ReflectionMethod使用實(shí)例
- PHP反射類ReflectionClass和ReflectionObject的使用方法
- PHP反射機(jī)制原理與用法詳解
- PHP反射使用實(shí)例和PHP反射API的中文說明
- 解析php中反射的應(yīng)用
- PHP反射機(jī)制用法實(shí)例
- php反射類ReflectionClass用法分析
- PHP 反射(Reflection)使用實(shí)例
- PHP基于反射機(jī)制實(shí)現(xiàn)自動(dòng)依賴注入的方法詳解
- PHP中的reflection反射機(jī)制測(cè)試?yán)?/a>
- PHP進(jìn)階學(xué)習(xí)之反射基本概念與用法分析
相關(guān)文章
PHP 優(yōu)化配置——加速你的VBB,phpwind,Discuz,IPB,MolyX
PHP 優(yōu)化配置——加速你的VBB,phpwind,Discuz,IPB,MolyX...2007-07-07不錯(cuò)的一篇面向?qū)ο蟮腜HP開發(fā)模式(簡(jiǎn)寫版)
不錯(cuò)的一篇面向?qū)ο蟮腜HP開發(fā)模式(簡(jiǎn)寫版)...2007-03-03MySql 按時(shí)間段查詢數(shù)據(jù)方法(實(shí)例說明)
oready網(wǎng)站的制作已經(jīng)接近尾聲。今天打算完成統(tǒng)計(jì)模塊功能,所以查找了下mysql按時(shí)間段查詢數(shù)據(jù)的語句,記錄一下。2008-11-11php ci 獲取表單中多個(gè)同名input元素值的代碼
這篇文章主要介紹了php ci 獲取表單中多個(gè)同名input元素值的代碼,需要的朋友可以參考下2016-03-03解析數(shù)組非數(shù)字鍵名引號(hào)的必要性
以下是對(duì)數(shù)組非數(shù)字鍵名引號(hào)的必要性進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-08-08