插件结构的好处就是实现了项目的可插拔性,我给我的项目添加一个插件,我就可以使用该插件的功能,我把这个插件删除,界面也不再显示该插件的相关信息。
介绍一下项目结构:
项目使用CI框架,
application
|--plugin(添加plugin文件夹,放置实现pluginInterface接口的文件)
| |--pluginInterface.php (接口)
|--controllers
| |--plugin(添加plugin文件夹,放置插件中的controller)
|--views
| |--plugin(放置插件中的view)
首先为了方便管理插件,我们提供一个接口,所有的插件提供者按接口实现自己的插件。
例如我们提供如下的接口:
<?php
interface pluginInterface {
function getLevel();
function getName();
function getMenus();
function getDescription();
function getVersion();
function getReleaseDate();
function getProviderName();
}
?>
插件提供者实现该接口
<?php
require_once dirname(dirname(dirname(__FILE__)))."/plugin/pluginInterface.php";
class xxxx implements pluginInterface{
function __construct()
{
}
function getLevel(){
return 1;
}
function getName(){
return 'xxx';
}
function getMenus(){
$sideBars ="<h3>xxx</h3>
<ul class='toggle'>
<li class='icn_my_application'>
<a href='".site_url()."/plugin/xx/xxx' class='colorMediumBlue bold spanHover'>xx首页</a>
</li>
<li class='icn_add_apps'>
<a href='".site_url()."/plugin/xxxxx/xxxx' class='colorMediumBlue bold spanHover'> xxxx</a></li>
</ul>";
return $sideBars;
}
function getDescription(){}
function getVersion(){}
function getReleaseDate(){}
function getProviderName(){}
}
?>
我们要有一个插件管理类,在该类中我们遍历application/plugin目录,查找实现了上述接口的所有类,通过反射机制来调用它的getMenus方法,获取该插件的功能列表。
插件管理类:pluginM.php
<?php
class pluginM extends CI_Model {
function __construct()
{
parent::__construct();
$this->load->helper('file');
$this->load->helper('path');
}
function traverse($path ,$returnarr) {
$entity = array();
$classname=array();
$current_dir = opendir($path); //opendir()返回一个目录句柄,失败返回false
while(($file = readdir($current_dir)) !== false) { //readdir()返回打开目录句柄中的一个条目
$sub_dir = $path. $file; //构建子目录路径
if($file == '.' || $file == '..') {
continue;
} else {if(is_dir($sub_dir)) { //如果是目录,进行递归
$returnarr=$this->traverse($sub_dir."/",$returnarr);
} else { //如果是文件
$index=strrpos ($file,".");
$filename=substr($file,0,$index);
$entity=array(
'classpath'=>$path . $file,
'classname'=>$filename);
array_push($returnarr, $entity);
}}
}
return $returnarr;
}
function run($functionname,$par){
$dir=dirname(dirname(__FILE__))."/plugin/";
$returnarr=array();
$arr=$this->traverse($dir,$returnarr);
for($i=0;$i<count($arr);$i++){
$classpat = $arr[$i]['classpath'];
require_once ($classpat);
$classname=$arr[$i]['classname'];
if($classname=="pluginInterface"){
continue;
}
$reflectionClass = new ReflectionClass($classname);
if ($reflectionClass->implementsInterface('pluginInterface')) {
try {
$cla= $reflectionClass->newInstance();
} catch (Exception $e) {
continue;
}
if(method_exists($cla, $functionname)){
$function= $reflectionClass->getmethod($functionname);
// $this->runfunction($classname,$classpat, "getName", $par);
$str=$function->invoke($cla,$par);
echo $str;
}
}
}
}
}
?>
在view中就可以通过
<?php $this->pluginM->run("getMenus","");?>
获取所有的插件的功能列表。