CodeIgniter 框架采用MVC模式,而MVC模式中起纽带做用的就是C(控制器),在控制器的中经过加载模型得到数据,将数据传到视图中进行展现。本课将实如今控制器中加载模型。php
1. 控制器的实现git
CodeIgniter 中控制器的做用很强大,经过继承CI_Controller 类就能够 $this->input 得到Input类的实例,其模型的调用方法是 $this->load->model('model'), 以后就能够经过 $this->model_name->调用相应模型的方法获取数据了。github
那么如何实现的呢?请看 CodeIgniter 中 CI_Controller 的源码。bootstrap
1 class CI_Controller { 2 3 private static $instance; 4 5 /** 6 * Constructor 7 */ 8 public function __construct() 9 { 10 self::$instance =& $this; 11 12 // Assign all the class objects that were instantiated by the 13 // bootstrap file (CodeIgniter.php) to local class variables 14 // so that CI can run as one big super object. 15 foreach (is_loaded() as $var => $class) 16 { 17 $this->$var =& load_class($class); 18 } 19 20 $this->load =& load_class('Loader', 'core'); 21 22 $this->load->initialize(); 23 24 log_message('debug', "Controller Class Initialized"); 25 } 26 27 public static function &get_instance() 28 { 29 return self::$instance; 30 } 31 }
它定义了一个静态成员变量,并在初始化时等于本身 self::$instance =& $this; 而后就能够经过 get_instance 静态函数得到该实例。数组
foreach 循环将 经过 load_class 函数管理的实例对象(很是重要的对象,如Input,Output等)赋值做为该类的成员变量,也就是说 $this->input 至关于 load_class('Input‘)。全部控制器类经过继承 Controller 基类,就能够一样得到这种便利!!框架
值得注意的是,与其余核心类不一样, Loader 类是在这里的构造函数处进行的,说明了 Loader 类对于 Controller 的重要性。函数
$this->load =& load_class('Loader', 'core'); 测试
2. Loader 类的 model 实现ui
Loader 类管理的 model 会比较多,上节课着重讲了 load_class 这种管理多个实例的原理,如下 model 函数就不难理解。this
按照 CodeIgniter 的管理,通常会定义几个搜索路径,因此能够在 Loader 中定义两个变量
protected $_ci_model_paths = array(); protected $_ci_models = array();
其中 $_ci_model_paths 表明路径, $_ci_models 表明已加载的模型。
在构造函数中,将$_ci_model_paths 初始化为 APPPATH,因为在本课中尚未分层,APPPATH 等同于当前目录,让 $_ci_model_paths = array('');
而后定义 model 函数
public function model($model, $name = '', $db_conn = FALSE) { if (is_array($model)) { foreach ($model as $babe) { $this->model($babe); } return; } if ($model == '') { return; } // model 是否在一个文件夹中,若是是的话,则分析路径和文件名 if (($last_slash = strrpos($model, '/')) !== FALSE) { $path = substr($model, 0, $last_slash + 1); $model = substr($model, $last_slash + 1); } if ($name = '') { $name = $model; } if (in_array($name, $this->_ci_models, TRUE)) { return; } $CI =& get_instance(); if (isset($CI->$name)) { show_error('The model name you are loading is the name of a resource that is already being used: '.$name); } $model = strtolower($model); foreach ($this->_ci_model_paths as $mod_path) { if ( ! file_exists($mod_path.'models/'.$path.$model.'.php')) { continue; } if ($db_conn !== FALSE AND ! class_exists('CI_DB')) { if ($db_conn === TRUE) { $db_conn = ''; } $CI->load->database($db_conn, FALSE, TRUE); } if ( ! class_exists('CI_Model')) { load_class('Model', 'core'); } require_once($mod_path.'models/'.$path.$model.'.php'); $model = ucfirst($model); $CI->$name = new $model(); $this->_ci_models[] = $name; return; } // 找不到模型 exit('Unable to locate the model you have specified: '.$model); }
1)经过 is_array 判断参数是否为数组,是的话,循环加载每个模型,这样就能够经过传递数组一次加载多个模型。(这也是一个很好的技巧哦,传参数的时候就能够既传单个值,也能够传数组)
2)model 能够包含路径,这样更利于 model 的组织,好比用户模块的 基本信息model, 积分 model 均可以放在 user 文件夹下,因此将路径按 '/' 拆分,就能够获得二级 path 和 model 名。
3)加载 model 后,该model 实例会做为 $this 的成员变量,用什么标识呢?若是不提供的话,默认就用 model 的名字。
好比 $this->load->model('news_model');
加载后,能够经过 $this->news_model 来访问加载的模型。
4)规范化
$this->load->model('News_model’); 这个用户想加载的类与 3)中一致,因此 $model 都会 strtolower 小写统一标记,这样不会出现两次加载了,另外实际在定义类的时候,news_model 对应的 class News_model;
经过参考这些,咱们能够提升写代码的优美度,也就是说用户可能在误输入大小写的状况下,依然保证能获得预期的效果。
3. 测试
根据前述讲述,针对上一节的代码,本次新加入的代码包括 Loader.php , Controller.php, Model.php( 暂时为空)
Welcome 类要继承 CI_Controller 类以下所示(放在 controllers 目录下)
<?php class welcome extends CI_Controller { function hello() { echo 'My first Php Framework!'; } function saysomething($str) { $this->load->model('test_model'); $info = $this->test_model->get_test_data(); echo $info; } }
为了测试 model 新建一个 models/test_model.php 文件,而后写入
<?php class Test_model extends CI_Model { function get_test_data() { return 'People you want in our model is Zhangzhenyu'; } }
其中 CI_Model 暂时能够为空, 在 core/Model.php 下定义一个 CI_Model 的空类便可,以保证程序的正确执行。
主执行文件也须要作相应的更改以下:
require('core/Controller.php'); function &get_instance() { return CI_Controller::get_instance(); } require('controllers/'.$class.'.php'); $CI = new $class(); call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
4. 测试结果
访问 http://localhost/learn-ci/index.php/welcome/hello
输出 People you want in our model is Zhangzhenyu