在Codeigeniter 框架基础上实现插件结构

        插件结构的好处就是实现了项目的可插拔性,我给我的项目添加一个插件,我就可以使用该插件的功能,我把这个插件删除,界面也不再显示该插件的相关信息。

介绍一下项目结构:

项目使用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","");?>

   获取所有的插件的功能列表。



你可能感兴趣的:(PHP,插件,反射调用,ci框架)