Codeigniter 3 拓展HMVC

在Codeiniter(以下统称CI) 2.X版本中,我们就通过拓展核心类库实现了HMVC,但是同样的代码,拿到CI 3中,就很有可能不好用了。

###拓展核心类库方式

官方的文档对拓展核心类有详细的说明:

你定义的类必须继承自父类。 你的类名和文件名必须以 MY_ 开头。(这是可配置的,见下文) 举个例子,要扩展原始的 Input 类,你需要新建一个文件 application/core/MY_Input.php,然后像下面这样定义你的类:

1class MY_Input extends CI_Input { 2 3}

CI 控制器加载的过程很简单,官方文档有图如下:

输入图片说明 我们可以看到,在控制器开始加载看,CI是做了Routing(路由)和Security(安全)的操作的,所以,我们需要重写,或者说,在CI拓展我们想要的功能,比如:HMVC

###2.0中扩展

在2.0版本中,笔者曾适用过Jens Segers开源的HMVC模块,代码的实现就是对Routee和Loader进行了重写。 Jens Segers的主页 核心的代码如下:

1 if (is_dir($source = $location . $module . '/controllers/')) { 2 $this->module = $module; 3 $this->directory = $relative . $module . '/controllers/'; 4 5 // 根目录下的模块? 6 if ($directory && is_file($source . $directory . '.php')) { 7 $this->class = $directory; 8 return array_slice($segments, 1); 9 } 10 11 // 子模块? 12 if ($directory && is_dir($source . $directory . '/')) { 13 $source = $source . $directory . '/'; 14 $this->directory .= $directory . '/'; 15 16 // 子控制器? 17 if (is_file($source . $directory . '.php')) { 18 return array_slice($segments, 1); 19 } 20 21 // 子文件夹包含有默认控制器? 22 if (is_file($source . $this->default_controller . '.php')) { 23 $segments[1] = $this->default_controller; 24 return array_slice($segments, 1); 25 } 26 27 // 子文件夹中的控制器? 28 if ($controller && is_file($source . $controller . '.php')) { 29 return array_slice($segments, 2); 30 } 31 } 32 33 // 控制器和文件夹名一样? 34 if (is_file($source . $module . '.php')) { 35 return $segments; 36 } 37 38 // 适用默认的控制器? 39 if (is_file($source . $this->default_controller . '.php')) { 40 $segments[0] = $this->default_controller; 41 return $segments; 42 } 43 }

很简单的拓展 就能实现HMVC模式了,同样的,还得重写Loader中的加载器,不然会找不到文件。

###CI 3 HMVC拓展 到了CI3中,上述方法已经不好用了,CI 3 对路由有了更多的考虑,在初始化路由时,就进行了解析。假设写MY_Ruter类,必须要重写3个方法: CI 2 Router构造

1 function __construct() 2 { 3 $this->config =& load_class('Config', 'core'); 4 $this->uri =& load_class('URI', 'core'); 5 log_message('debug', "Router Class Initialized"); 6 }

CI 3 Router构造

1public function __construct($routing = NULL) 2 { 3 $this->config =& load_class('Config', 'core'); 4 $this->uri =& load_class('URI', 'core'); 5 6 $this->enable_query_strings = ( ! is_cli() && $this->config->item('enable_query_strings') === TRUE); 7 8 9 is_array($routing) && isset($routing['directory']) && $this->set_directory($routing['directory']); 10 11 $this->_set_routing(); 12 13 14 if (is_array($routing)) 15 { 16 empty($routing['controller']) OR $this->set_class($routing['controller']); 17 empty($routing['function']) OR $this->set_method($routing['function']); 18 } 19 20 log_message('info', 'Router Class Initialized'); 21 }

可以看到,在CI3的构造方法中就已经对URL进行解析,方法的调用过程为: _set_routing() -> _validate_request() -> _parse_routes() -> _set_request() 那我们为了要实现HMVC,这几个方法是必然要按照我们自己的方法实现的。 _validate_request 中 我们加入部分验证,即可达到简单的HMVC

1 if (is_dir($source = $relative . $module . '/controllers/')) { 2 $this->module = $module; 3 $this->directory = '../'.$location.$module . '/controllers/'; 4 5 6 // 如果 有 application/$module/controollers/$directory.php 文件 7 if ($directory && is_file($source . ucfirst($directory) . '.php')) { 8 return array_slice($segments, 1); 9 } 10 11 //如果application/$module/$directory 是一个文件夹 12 if ($directory && is_dir($source . $directory . '/')) { 13 $source = $source . $directory . '/'; 14 $this->directory .= $directory . '/'; 15 // index.php/$modules/$directory/$controller 16 //如果包含 控制器 $controller 17 if ($controller && is_file($source . ucfirst($controller) . '.php')) { 18 return array_slice($segments, 2); 19 } 20 21 //如果有默认控制器 22 if (is_file($source . $this->default_controller . '.php')) { 23 $segments[1] = $this->default_controller; 24 return array_slice($segments, 1); 25 } 26 27 //如果有 application/$module/$directory.php 28 if (is_file($source . $directory . '.php')) { 29 return array_slice($segments, 1); 30 } 31 } 32 33 //如果有 application/$module/$module.php 34 if (is_file($source . $module . '.php')) { 35 return $segments; 36 } 37 38 // 默认控制器 39 if (is_file($source . $this->default_controller . '.php')) { 40 $segments[0] = $this->default_controller; 41 return $segments; 42 } 43 }

为了让CI_ROUTER知道我们模块拓展的位置,我们在配置文件中加入选项,并在CI_ROUTER的构造器中加入如下代码:

1$locations = $this->config->item('modules_locations'); 2 3 if (!$locations) { 4 $locations = array('modules/'); 5 } else if (!is_array($locations)) { 6 $locations = array($locations); 7 } 8 9 $this->config->set_item('modules_locations', $locations);

操作完以上步骤,就可以实现大部分HMVC的拓展了。 本文代码:https://git.oschina.net/liwenlong/Codeigniter-3-HMVC.git 说明:CI3中对控制器大小写由严格的控制了,为了符合CI3的一贯规则,所以我们使用了ucfirst()方式寻找首字母大写的类名,一定要注意。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Java日期时间API系列31

  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Codeigniter 3 拓展HMVC - HelloWorld