久久er精品视频_先锋影院在线亚洲_影音先锋一区_性色av香蕉一区二区

中山php|最優網絡中山做網站 中山php建站

最優良人

2011/08/26 at 00:06

什么是php反射機制以及利用php反射機制實現可插拔可擴展的插件架構

反射是什么?
它是指在PHP運行狀態中,擴展分析PHP程序,導出或提取出關于類、方法、屬性、參數等的詳細信息,包括注釋。這種動態獲取的信息以及動態調用對象的方法的功能稱為反射API。

反射是操縱面向對象范型中元模型的API,其功能十分強大,可幫助我們構建復雜,可擴展的應用。其用途如:自動加載插件,自動生成文檔,甚至可用來擴充PHP語言。php反射api由若干類組成,可幫助我們用來訪問程序的元數據或者同相關的注釋交互。借助反射我們可以獲取諸如類實現了那些方法,創建一個類的實例(不同于用new創建),調用一個方法(也不同于常規調用),傳遞參數,動態調用類的靜態方法。
*
**
反射api是php內建的oop技術擴展,包括一些類,異常和接口,綜合使用他們可用來幫助我們分析其它類,接口,方法,屬性,方法和擴展。這些oop擴展被稱為反射,位于php源碼/ext/reflection目錄下。

可以使用反射api自省反射api本身(這可能就是反射最初的意思,自己"看"自己):
<?php
Reflection::export(new ReflectionExtension('reflection'));
?>
幾乎所有的反射api都實現了reflector接口,所有實現該接口的類都有一個export方法,該方法打印出參數對象的相關信息。
使用get_declared_classes()獲取所有php內置類,get_declared_interfaces();
get_defined_functions();
get_defined_vars(); get_defined_constants();可獲取php接口,方法,變量,常量信息。

**
***
反射初探:
<?php
//定義一個自定義類
class MyTestClass{

public function testFunc($para0='defaultValue0'){

}
}
//接下來反射它
foreach(get_declared_classes() as $class){
//實例化一個反射類
$reflectionClass = new ReflectionClass($class);
//如果該類是自定義類
if($reflectionClass->isUserDefined()){
//導出該類信息
Reflection::export($reflectionClass);
}
}
?>
以上片段實例如何查看自定義類的基本信息。
描述數據的數據被稱為元數據,用反射獲取的信息就是元數據信息,這些信息用來描述類,接口方法等等。(元---》就是原始之意,比如元模型就是描述模型的模型,比如UML元模型就是描述UML結構的模型),元數據進一步可分為硬元數據(hard matadata)和軟元數據(soft metadata),前者由編譯代碼導出,如類名字,方法,參數等。
后者是人為加入的數據,如phpDoc塊,php中的屬性等。
***
****
現在商業軟件很多都是基于插件架構的,比如eclipse,和visual studio,netbeans等一些著名IDE都是基于插件的GUI應用。第三方或本方開發插件時,必須導入定義好的相關接口,然后實現這些接口,最后把實現的包放在指定目錄下,宿主應用程序在啟動時自動檢測所有的插件實現,并加載它們。如果我們自己想實現這樣的架構也是可能的。
<?php
//先定義UI接口
interface IPlugin {
//獲取插件的名字
public static function getName();
//要顯示的菜單項
function getMenuItems();
//要顯示的文章
function getArticles();
//要顯示的導航欄
function getSideBars();
}
//一下是對插件接口的實現
class SomePlugin implements IPlugin {
public function getMenuItems() {
//返回菜單項
return null;
}
public function getArticles() {
//返回我們的文章
return null;
}
public function getSideBars() {
//我們有一個導航欄
return array('SideBarItem');
}
//返回插件名
public static function getName(){
return "SomePlugin";
}
}
?>
php中也有使用插件的解決方案,不像eclipse。

使用我們的插件:1.先使用get_declared_classes()獲取所有已加載類。2.遍歷所有類,判斷其是否實現了我們自定義的插件接口IPlugin。3.獲取所有的插件實現。4.在宿主應用中與插件交互
下面這個方法幫助我們找到實現了插件接口的所有類:
function findPlugins() {
$plugins = array();
foreach(get_declared_classes() as $class) {
$reflectionClass = new ReflectionClass($class);
//判斷一個類是否實現了IPlugin接口
if($reflectionClass->implementsInterface('IPlugin')) {
$plugins[] = $reflectionClass;
}
}
return $plugins;
}
注意到所有的插件實現是作為反射類實例返回的,而不是類名本身,或是類的實例。因為如果使用反射來調用方法還需要一些條件判斷。

判斷一個類是否實現了某個方法使用反射類的hasMethod()方法。
接下來我們把所有的插件菜單項放在一個菜單上。
function integratePlugInMenus() {
$menu = array();
//遍歷所有的插件實現
foreach(findPlugins() as $plugin) {
//判斷插件是否實現了getMenuItems方法
if($plugin->hasMethod('getMenuItems')) {
/*實例化一個方法實例(注意當你將類和方法看成概念時,它們就可以有實例,就像"人"這個概念一樣),該方法返回的是ReflectionMethod的實例*/
$reflectionMethod = $plugin->getMethod('getMenuItems');
//如果方法是靜態的
if($reflectionMethod->isStatic()) {
//調用靜態方法,注意參數是null而不是一個反射類實例
$items = $reflectionMethod->invoke(null);
} else {
//如果方法不是靜態的,則先實例化一個反射類實例所代表的類的實例。
$pluginInstance = $plugin->newInstance();
//使用反射api來調用一個方法,參數是通過反射實例化的對象引用
$items = $reflectionMethod->invoke($pluginInstance);
}
//合并所有的插件菜單項為一個菜單。
$menu = array_merge($menu, $items);
}
}
return $menu;
}
這里主要用到的反射方法實例的方法調用:
public mixed invoke(stdclass object, mixed args=null);
請一定搞清楚我們常規方法的調用是這種形式:$objRef->someMethod($argList...);
因為使用了反射,這時你在想調用一個方法時形式變為:
$reflectionMethodRef->invoke($reflectionClassRef,$argList...);
如果使用反射調用方法,我們必須實例化一個反射方法的實例,如果是實例方法還要有一個實例的引用,可能還需傳遞必要的參數。當調用一個靜態方法時,顯式傳入null作為第一參數。
對插件類實現的其他方法有類似的處理邏輯,這里不再敷述。
以下是我的一個簡單測試:
<?php
/**
* 定義一個插件接口
* */
interface IPlugIn
{
/**
* getSidebars()
*
* @return 返回側導航欄
*/
public function getSidebars();
/**
* GetName()
*
* @return 返回類名
*/
public static function GetName();
}

/*下面是對插件的實現,其實應該放在不同的文件中,甚至是不同的包中*/
class MyPlugIn implements IPlugIn
{
public function getSidebars()
{
//構造自己的導航欄
$sideBars = '<div><ul >
<li><a href="">m1</a>
</li>
<li><a href="">m2</a>
</li>
</ul>
</div>';
return $sideBars;
}
public static function GetName()
{
return 'MyPlugIn';
}
}
//第二個插件實現;
class MyPlugIn2 implements IPlugIn
{
public function getSidebars()
{
//構造自己的導航欄
$sideBars = '<div><ul >
<li><a href="">mm1</a>
</li>
<li><a href="">mm2</a>
</li>
</ul>
</div>';
return $sideBars;
}
public static function GetName()
{
return 'MyPlugIn2';
}
}

//在宿主程序中使用插件
class HostApp
{

public function initAll()
{
// 初始化各個部分
echo "yiqing95.";
$this->renderAll();
}
//渲染GUI格部分
function renderAll(){
$rsltSidebars="<table>";
foreach($this->integrateSidebarsOfPlugin() as $sidebarItem){
$rsltSidebars.="<tr><td>$sidebarItem</td></tr>";
}
$rsltSidebars.="</table>";

echo $rsltSidebars;
}
/*加載所有的插件實現:*/
protected function findPlugins()
{
$plugins = array();
foreach (get_declared_classes() as $class) {
$reflectionClass = new ReflectionClass($class);
if ($reflectionClass->implementsInterface('IPlugin')) {
$plugins[] = $reflectionClass;
}
}
return $plugins;
}
/**加載組裝所有插件實現***/
protected function integrateSidebarsOfPlugin()
{
$sidebars = array();
foreach ($this->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);
$sidebars[]=$items;
}
return $sidebars;
}

}
//運行程序:
$entryClass =new HostApp();
$entryClass->initAll();
?>
****
××××
$reflectionClass = new ReflectionClass("IPlugIn");
echo $reflectionClass-> getDocComment();
這段代碼可以幫助我們獲取類的文檔注釋,一旦我們獲取了類的注釋內容我們就可以擴展我們的類功能,比如先獲取注釋,然后分析注釋使用docblock tokenizer 『pecl擴展』,或使用自帶的Tokenizer類又或者使用正則表達式,字符串函數來解析注釋文檔,你可以在注釋中加入任何東西,包括指令,在使用反射調用前可判斷這些通過注釋傳遞的指令或數據:
<?php
//"分析相關的注釋數據"
analyse($reflectionClass-> getDocComment());//analyse是自己定義的?。。?br /> //根據分析的結果來執行方法,或者傳遞參數等
if(xxxx){
$reflectionMethod->invoke($pluginInstance) ;
}
?>
因為注釋畢竟是字符串,可以使用任何字符串解析技術,提取有用的信息,再根據這些信息來調用方法,就是說程序的邏輯不光可由方法實現決定,還可能由注釋決定(前提是你使用了反射,注釋格式嚴格有要求)。
××××
*****
反射api和其他類一樣可被繼承擴展,所以我們可以為這些api添加自己的功能。結合自定義注釋標記。就是以@開頭的東東,標注(Java中稱為annotation),.net中稱為屬性attribute(或稱為特性)。然后擴展Reflection類,就可以實現強大的擴展功能了。
值得一提的是工廠方法設計模式(GOF之一),也常使用反射來實例化對象,下面是示例性質的偽碼:
Class XXXFactory{
function getInstance($className){
$reflectionClass =new ReflectionClass($className);
return $reflectionClass->newInstance();
}
//使用接口的那個類實現,可能來自配置文件
function getInstance(){
$pathOfConfig = "xxx/xx/XXXImplement.php";
$className= Config->getItem($pathOfClass,'SomeClassName');
return $this->getInstance($className);
}
}
*****

標簽:,
-
久久er精品视频_先锋影院在线亚洲_影音先锋一区_性色av香蕉一区二区
欧美精品久久一区二区| 欧美v亚洲v综合ⅴ国产v| 欧美日韩美女在线| 中文无字幕一区二区三区| 亚洲精品综合在线| 欧美日韩一卡| 欧美专区18| 久久久777| 亚洲精品一区二区三区樱花| 91久久精品国产| 欧美屁股在线| 香蕉成人啪国产精品视频综合网| 亚洲欧美日韩一区二区在线| 国产综合在线视频| 欧美77777| 欧美视频导航| 久久婷婷人人澡人人喊人人爽 | 亚洲免费在线视频| 亚洲欧美日韩综合国产aⅴ| 狠狠色狠狠色综合日日小说| 欧美激情a∨在线视频播放| 欧美精品乱人伦久久久久久 | 99精品国产99久久久久久福利| 日韩视频在线免费观看| 国产欧美va欧美不卡在线| 久久一区二区三区超碰国产精品| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美国产专区| 国产精品v一区二区三区| 久久亚洲一区二区三区四区| 欧美美女视频| 毛片精品免费在线观看| 欧美日韩第一区| 久久久久久久久久久一区 | 久久夜色精品亚洲噜噜国产mv| 中文国产一区| 另类成人小视频在线| 午夜激情一区| 欧美日韩的一区二区| 久久蜜桃av一区精品变态类天堂| 欧美日本在线播放| 欧美成人嫩草网站| 国产欧美一区二区三区另类精品| 亚洲欧洲在线免费| 樱花yy私人影院亚洲| 亚洲专区在线视频| 一区二区免费在线视频| 久久久久久久综合日本| 亚洲欧美成人综合| 欧美日韩国产一区二区三区地区| 免费91麻豆精品国产自产在线观看| 国产精品日韩二区| 在线亚洲国产精品网站| 99精品国产在热久久下载| 麻豆成人在线播放| 久久亚洲欧洲| 国模私拍一区二区三区| 亚洲免费一在线| 亚洲欧美国产精品桃花| 欧美色区777第一页| 亚洲精品欧美激情| 99re66热这里只有精品3直播| 久热re这里精品视频在线6| 久久米奇亚洲| 激情成人av| 久久野战av| 欧美激情国产精品| 亚洲国产日韩欧美在线图片 | 亚洲欧洲视频| 99精品免费视频| 欧美看片网站| 日韩系列欧美系列| 亚洲一区二区三区视频| 国产精品国码视频| 亚洲欧美另类综合偷拍| 久久国产精品99国产精| 国产亚洲精品aa| 久久久99免费视频| 欧美大香线蕉线伊人久久国产精品| 在线精品国产欧美| 欧美肥婆在线| 一本久道综合久久精品| 新67194成人永久网站| 国产亚洲综合性久久久影院| 久久精品国产亚洲高清剧情介绍| 老司机一区二区| 亚洲精品在线免费| 欧美性一区二区| 校园激情久久| 亚洲第一伊人| 亚洲欧美www| 在线观看日产精品| 欧美日韩三区四区| 欧美亚洲在线| 亚洲国产黄色片| 性色av一区二区三区在线观看| 黑人一区二区三区四区五区| 欧美高清在线| 亚洲欧美亚洲| 亚洲欧洲精品一区二区| 欧美与欧洲交xxxx免费观看| 亚洲国产人成综合网站| 国产精品久久久久久久7电影| 久久精品一区二区三区四区| 亚洲另类黄色| 另类图片综合电影| 亚洲自拍电影| 亚洲激情成人网| 国产麻豆精品theporn| 美腿丝袜亚洲色图| 久久艳片www.17c.com| 亚洲激情视频网| 亚洲美女黄色| 篠田优中文在线播放第一区| 在线成人av| 国产精品一二三视频| 免费久久久一本精品久久区| 亚洲免费视频一区二区| 亚洲国产你懂的| 欧美一级片在线播放| 日韩视频国产视频| 在线观看欧美成人| 国产欧美一区二区视频| 欧美日韩国产综合久久| 美女主播一区| 久久三级福利| 久久精品国产一区二区三区| 一区二区精品在线观看| 亚洲激情在线观看视频免费| 另类酷文…触手系列精品集v1小说| 亚洲综合激情| 一区二区欧美激情| 亚洲精选在线| 日韩西西人体444www| 亚洲黄色免费| 亚洲区欧美区| 亚洲人成在线观看一区二区| 亚洲第一天堂av| 激情成人综合网| 黄色欧美日韩| 一区二区在线观看视频| 韩国三级电影久久久久久| 国产在线乱码一区二区三区| 国产精品女人网站| 国产精品毛片在线| 国产精品免费网站| 国产免费成人av| 国产日韩一区二区| 国产婷婷成人久久av免费高清| 国产精品一区二区三区成人| 国产精品自拍网站| 国产亚洲精品v| 国内免费精品永久在线视频| 精品91视频| 亚洲欧洲日夜超级视频| 亚洲乱码久久| 亚洲小视频在线| 欧美亚洲综合久久| 久久久青草婷婷精品综合日韩| 免费不卡亚洲欧美| 亚洲电影在线免费观看| 亚洲精品欧美一区二区三区| 国产精品99久久久久久人| 亚洲欧美激情四射在线日 | 久久久青草青青国产亚洲免观| 久久天堂精品| 亚洲国产91精品在线观看| 亚洲精品欧美日韩| 亚洲免费中文| 久久在线视频| 欧美四级在线观看| 国产综合久久| 日韩视频免费观看| 欧美一级网站| 欧美国产精品久久| 亚洲一二三区精品| 久久人人爽人人| 欧美三级视频在线| 国产一区二区主播在线| 亚洲免费不卡| 久久久亚洲一区| 亚洲精品美女免费| 欧美一区二区三区在线看| 欧美成年人视频网站| 国产精品欧美日韩一区| 亚洲高清网站| 久久精品30| 日韩亚洲在线观看| 久久婷婷丁香| 国产视频一区三区| 99re在线精品| 美日韩精品视频| 亚洲一区二区三区久久| 欧美成ee人免费视频| 国产亚洲综合精品| 亚洲永久免费视频| 亚洲日本成人网| 久久一二三区| 国产一区二区日韩精品| 亚洲一区二区三区精品视频|