PHP基于反射機(jī)制實(shí)現(xiàn)插件的可插拔設(shè)計(jì)詳解
本文實(shí)例講述了PHP基于反射機(jī)制實(shí)現(xiàn)插件的可插拔設(shè)計(jì)。分享給大家供大家參考,具體如下:
說(shuō)PHP和ASP等同的朋友們可以就此打住了,PHP支持反射,而且還是非常的強(qiáng)大。好了,我們開始今天的話題。
功能描述:
頁(yè)面擁有一個(gè)主導(dǎo)航菜單,里頭有默認(rèn)連接若干。
插件統(tǒng)一存放在一個(gè)目錄,插件載入后會(huì)自動(dòng)在導(dǎo)航菜單中增加上自己所需的鏈接。
插件載入時(shí)可執(zhí)行一定的操作。
動(dòng)態(tài)增刪插件無(wú)需改動(dòng)代碼。
最終效果:
首頁(yè),插件1,插件2
"首頁(yè)"是系統(tǒng)自帶的菜單項(xiàng)。"插件1"和"插件2"是由插件注冊(cè)的菜單項(xiàng)。
實(shí)現(xiàn)過(guò)程:
1. 文件結(jié)構(gòu)
Learn
plugin
plugin1.php
plugin2.php
test.php
如此設(shè)計(jì)后,頁(yè)面入口為test.php,插件都存放在plugin目錄下,只要遍歷plugin目錄就可以找到所有的插件了。
2. 設(shè)計(jì)插件接口
interface IPlugin{ static function getname(); static function init(); static function getMenu(); }
3. 插件內(nèi)部實(shí)現(xiàn)接口
Plugin1實(shí)現(xiàn)接口:
<?php Class Welcome implements IPlugin{ static function getname(){ return 'Welcome (Plugin)'; } static function getMenu(){ return array( 'text'=>'插件1′, 'href'=>'http://www.google.com' ); } static function init(){ echo self::getname() . " 載入中…<br />"; } } ?>
Plugin2實(shí)現(xiàn)接口:
<?php Class ShowAD implements IPlugin{ static function getname(){ return 'Show AD (Plugin)'; } static function getMenu(){ return array( 'text'=>'插件2′, 'href'=>'http://www.live.com' ); } static function init(){ echo self::getname() . " 載入中…<br />"; } } ?>
4. 主頁(yè)面初始化主導(dǎo)航菜單
$menu[] = array( 'text'=>'首頁(yè)', 'href'=>'/test.php' );
5. 遍歷插件目錄,載入全部插件
$pluginPath = $_SERVER['DOCUMENT_ROOT'] . '/plugin'; $dirHd = opendir($pluginPath); while ($file = readdir($dirHd)){ $pluginFilePath = $pluginPath . '/' . $file; if($file!='.' && $file!='..' && is_file($pluginFilePath)){ include "$pluginFilePath"; } }
6. 過(guò)濾出實(shí)現(xiàn)了IPlugin接口的插件,并執(zhí)行插件注入操作。
// 反射執(zhí)行方法(注入菜單) foreach (get_declared_classes() as $class){ $refClass = new ReflectionClass($class); if($refClass->implementsInterface('IPlugin')){ //插件初始化 $refClass->getMethod('init')->invoke(null); //獲取注入菜單 $menuItem = $refClass->getMethod('getMenu')->invoke(null); //合并菜單項(xiàng) $menu = array_merge($menu, array($menuItem)); } }
7. 主頁(yè)面輸出菜單HTML
foreach ($menu as $m){ echo "<a href='{$m['href']}'>{$m['text']}</a> "; }
注意第6部就是PHP的反射操作,是不是很簡(jiǎn)單呢。分析下其中代碼,一個(gè)完整的反射操作時(shí)機(jī)只有2行代碼!
$refClass = new ReflectionClass($class); $menuItem = $refClass->getMethod('getMenu')->invoke(null);
好了,反射的基本功能就介紹到這了。當(dāng)然了,PHP的反射功能不僅僅如此,有興趣的自己發(fā)掘去吧。
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《PHP數(shù)組(Array)操作技巧大全》、《php排序算法總結(jié)》、《PHP常用遍歷算法與技巧總結(jié)》、《PHP數(shù)據(jù)結(jié)構(gòu)與算法教程》、《php程序設(shè)計(jì)算法總結(jié)》、《PHP數(shù)學(xué)運(yùn)算技巧總結(jié)》、《php正則表達(dá)式用法總結(jié)》、《PHP運(yùn)算與運(yùn)算符用法總結(jié)》、《php字符串(string)用法總結(jié)》及《php常見數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
相關(guān)文章
PHP數(shù)字前補(bǔ)0的自帶函數(shù)sprintf 和number_format的用法(詳解)
下面小編就為大家?guī)?lái)一篇PHP數(shù)字前補(bǔ)0的自帶函數(shù)sprintf 和number_format的用法(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02php 讀取文件頭判斷文件類型的實(shí)現(xiàn)代碼
以下是對(duì)使用php實(shí)現(xiàn)讀取文件頭判斷文件類型,支持圖片、rar、exe等后綴進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下2013-08-08php使用sql數(shù)據(jù)庫(kù) 獲取字段問(wèn)題介紹
由于sql server中,ntext和nvarchar字段是用unicode編碼存儲(chǔ)內(nèi)容的,因此php通過(guò)mssql擴(kuò)展讀取帶ntext和nvarchar類型字段的時(shí)候會(huì)抱錯(cuò)2013-08-08php實(shí)現(xiàn)購(gòu)物車功能(以大蘋果購(gòu)物網(wǎng)為例)
本文主要介紹了php實(shí)現(xiàn)購(gòu)物車功能(以大蘋果購(gòu)物網(wǎng)為例)的實(shí)現(xiàn)方法,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03php下載文件超時(shí)時(shí)間的設(shè)置方法
這篇文章W主要介紹了php下載文件超時(shí)時(shí)間的設(shè)置方法2016-10-10php中使用addslashes函數(shù)報(bào)錯(cuò)問(wèn)題的解決方法
php中使用addslashes函數(shù)報(bào)錯(cuò)問(wèn)題的解決方法,需要的朋友可以參考下2013-02-02PHP基于數(shù)組實(shí)現(xiàn)的堆棧和隊(duì)列功能示例
這篇文章主要介紹了PHP基于數(shù)組實(shí)現(xiàn)的堆棧和隊(duì)列功能,結(jié)合實(shí)例形式分析了php基于數(shù)組的array_push()、array_pop()、array_shift()等函數(shù)實(shí)現(xiàn)堆棧與隊(duì)列的入棧、出棧以及隊(duì)列的添加、刪除等相關(guān)操作技巧,需要的朋友可以參考下2018-01-01