使用过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夹子

 

widget实现

 

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

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

 

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

视图中直接使用

 

 
  
  1. <?php Widget::foot();?> 

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