使用过YII的人会知道YII使用module实现HMVC(可参见 http://baike.baidu.com/view/3256424.htm)使用相当方便。

因为工作需要我用到了codeigniter(以下简称ci)做开发,想在CI中实现HMVC当然通过修改ci的源码肯定能实现,ci论坛中也讨论了好几种方法,自己寻思着用了一种最简单的方式widget实现了简单的HMVC,当然不是完整意义上的HMVC不过也能适用于一般情况。

上代码,如果工作需要我肯定还会不断完善这样widget的方式

首先,我扩展了ci的控制器

 

   
   
   
   
  1. /** 
  2.  * 控制器基类 
  3.  * 前台控制器继承MY_Controller 
  4.  * 后台控制器继承MY_Admin_Controller,同时MY_Admin_Controller 继承自MY_Controller 
  5.  * @author      ricky 
  6.  * @since       2010/07/23 
  7.  * @copyright   tusheng 
  8.  * 
  9.  */ 
  10. class MY_Controller extends Controller 
  11.      
  12.     public function MY_Controller() 
  13.     { 
  14.         parent :: Controller(); 
  15.     } 
  16.     /** 
  17.      * load widget class if isset $name and called widget() in controller class 
  18.      * @param string $name 
  19.      */ 
  20.     protected function widget($name = ''
  21.     { 
  22.         if (isset($name) && $name != ''
  23.         { 
  24.             require_once APPPATH.'widgets/'.$name.EXT; 
  25.         } 
  26.     } 

接着创建了widget夹子

 

CI 实现 widget_第1张图片

widget实现

 

   
   
   
   
  1. /** 
  2.  * 单例模式实现widget. 
  3.  *  
  4.  * widget即小组件包含自己的控制器,视图,模型(可以共用普通model)。 
  5.  * 通常用来实现各页面都有的公共部分 
  6.  *  
  7.  * @author ricky 
  8.  * @since  2010/12/24 09:00 
  9.  */ 
  10. class Widget extends MY_Controller 
  11.     /** 
  12.      * 静态ci对象 
  13.      */ 
  14.     public static $_ci
  15.      
  16.     /** 
  17.      * 私有构造函数用于实现单例模式 
  18.      */ 
  19.     private function __construct() 
  20.     { 
  21.         parent::MY_Controller(); 
  22.         self::$_ci = & get_instance();//php 5.3中self改为static 
  23.     } 
  24.     /** 
  25.      * 获取当前类名 
  26.      */ 
  27.     private static function _getClass() 
  28.     { 
  29.         return __CLASS__
  30.     } 
  31.     /** 
  32.      * 普通控制器方法 
  33.      */ 
  34.     public static function foot() 
  35.     { 
  36.         /** 
  37.          * 开发自己的方法必需包含此两行代码 
  38.          */ 
  39.         $class = self::_getClass(); 
  40.         $instance = & new $class();//延迟绑定 
  41.          
  42.         $instance->load->model('m_article','article_widget');//notice : 这里load model 如果已在控制器中注意命名空间污染的问题,所以这里使用了'article_widget'而不是'article' 
  43.         $category = $instance->article_widget->getArticleCategory(); 
  44.         if (is_array($category) && !emptyempty($category)) 
  45.         { 
  46.             foreach ($category as $key=>$value
  47.             { 
  48.                 $article[$value['id']] = $instance->article_widget->getArticle('1',intval($value['id'])); 
  49.             } 
  50.         } 
  51.         $data['article'] = $article
  52.         $instance->load->view('foot',$data); 
  53.     }  
  54.     /** 
  55.      * left category tree. 
  56.      *  
  57.      *  
  58.      */ 
  59.     public static function category() 
  60.     { 
  61.         $class = self::_getClass(); 
  62.         $instance = & new $class(); 
  63.          
  64.         $instance->load->model('m_category','category_widget'); 
  65.         $data['categoryTree'] = $instance->category_widget->getCategory(); 
  66.         $instance->load->view('left',$data); 
  67.     } 
  68.      

当然继承自MY_Controller 的控制器中需要调用父类的widget方法

 

   
   
   
   
  1. //load widget 
  2.         $this->widget('widget'); 

视图中直接使用

 

   
   
   
   
  1.  

最后如果需要参数等可自行修改