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