1. 程式人生 > >ci框架原始碼解析

ci框架原始碼解析



1.index.php :入口檔案
|-->define('ENVIRONMENT')  |主要用於設定errors日誌輸出級別
|-->$system_path |設定系統路徑
|-->設定BASEPATH、FCPATH、SYSDIR、APPPATH等    |設定路徑資訊變數,為載入相應檔案資訊準備
|-->require_once BASEPATH.core/CodeIgniter.php | 最後載入CodeIgniter.php作為總控制器




2.CodeIgniter.php載入過程,主要用於載入core核心目錄下相應檔案


|-->require(BASEPATH.'core/Common.php');  |載入core目錄下的Common檔案,見2.1解析

|-->require(APPPATH.'config/'.ENVIRONMENT.'/constants.php'); |載入constants目錄,與開發環境無關時直接使用config目錄下的constants目錄
|-->get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));   |設定子檔案,擴充套件類的字首
|-->$BM =& load_class('Benchmark', 'core');  |載入benchmark類,mark記錄當前的時間
|-->$EXT =& load_class('Hooks', 'core');     |載入core目錄下的Hooks鉤子類

|-->$EXT->_call_hook('pre_system');  |呼叫_call_hook(pre_system),根據pre_system內部呼叫_run_hook執行鉤子,在系統開始正式工作前作預處理
|-->$CFG =& load_class('Config', 'core');    |繼續執行core下的Config配置檔案,
|-->$CFG->_assign_to_config($assign_to_config); 
|-->|$this->set_item($key, $val);      |解析指定給config的配置檔案,實質為對config[]賦值

|-->$UNI =& load_class('Utf8', 'core');      |載入了UTF-8編碼類,CI_Utf8
|-->$URI =& load_class('URI', 'core');       |載入core目錄的URI類,CI_URI
|-->$RTR =& load_class('Router', 'core');    |設定route路由及覆蓋資訊,見2.2解析
|-->_set_routing()
|-->_set_overrides()
|-->$OUT =& load_class('Output', 'core');    |例項化輸出類,載入core目錄下的output檔案
|-->$OUT->_display_cache($CFG, $URI)         |判斷是否存在頁面快取,是則輸出檔案
|-->$SEC =& load_class('Security', 'core');  |載入core目錄下的安全處理檔案
|-->$IN=& load_class('Input', 'core');      |例項化輸入類,載入core目錄下的input檔案
|-->$LANG =& load_class('Lang', 'core');     |載入語言類
|-->require BASEPATH.'core/Controller.php';  |載入基本控制器類,見2.3解析
|-->require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';  |嘗試載入擴充套件的自定義子類控制器
|-->include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php');  |載入自定義控制器下的控制器類
|-->$BM->mark('loading_time:_base_classes_end'); |設定一個benchmark測試點
|-->$class  = $RTR->fetch_class();    |分別獲取uri地址的控制器類名和方法名
|-->$method = $RTR->fetch_method();
|-->if ( ! class_exists($class)              |判斷方法及類是否合理
OR strncmp($method, '_', 1) == 0
OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
)
|-->$EXT->_call_hook('pre_controller');      |處理器執行前進行預處理,並做benchmark設定
|-->$CI = new $class();                      |獲取執行的控制器例項,例項化構造器
|-->$EXT->_call_hook('post_controller_constructor');  |例項化控制器類後的鉤子處理
|-->if (method_exists($CI, '_remap'))
|-->$CI->_remap($method, array_slice($URI->rsegments, 2))  |如果控制器存在_remap()方法,則執行, 判斷條件$CI為控制器類 
|-->else |判斷方法在類當中的存在似,如果不存在,則設定
|-->call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2)); |最終傳遞引數供呼叫控制類方法
|-->$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end'); |benchmark標記時間結束點
|-->$EXT->_call_hook('post_controller');     |控制器生存週期,在控制器執行完成後執行後續操作
|-->$OUT->_display();  |輸出頁面進行展示
|-->$EXT->_call_hook('post_system');         |請求生存週期完成後的終結操作
|-->$CI->db->close();                        |自動關閉資料庫資源




2.1 Core/Common.php載入
|-->function is_php($version)                |用於比較版本號的函式
|-->function is_really_writable($file)       |用於判斷是否可以寫檔案,在不同的系統中可靠程度不同,
      W中通過判斷is_readonly,U中如果safe_mode為開則不確定性
|-->function load_class($class, $directory = 'libraries', $prefix = 'CI_')   |用於載入目錄下的PHP檔案的class類
|-->foreach (array(APPPATH, BASEPATH) as $path)    |分別在application和system目錄下輪循
|-->file_exists($path.$directory.'/'.$class.'.php' |找到對應的PHP檔案
|-->require($path.$directory.'/'.$class.'.php');   |require載入對應的PHP檔案內的類,加了字首,此處可擴充套件
|-->break;   |如正確載入則退出,否則繼續嘗試載入檔案
|-->file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php')  |自擴充套件的class類,如My_Test
|-->if ($name === FALSE)   |如果$name不存在,則exit()退出 ,(在自定義類載入時,此處可作為擴充套件點,增加邊際條件)
|-->is_loaded($class);     |確類已經載入
|-->$_classes[$class] = new $name();  |載入至靜態的classes數祖中,用於快取,呼叫時首先從classes中獲取
|-->function is_loaded($class = '')                      
|-->設定$_is_loaded數祖,引數$class不為空,判斷是否存在gf $_is_loaded,否則設定
|-->function &get_config($replace = array())|用於獲取Config的例項化檔案
|-->static $_config;       |定義config型別
|-->$file_path = APPPATH.'config/config.php';      |確定application目錄路徑下定義的config.php的路徑
|-->require($file_path);   |載入application/config/config.php類
|-->count($replace) > 0    |對於config.php中定義的變數,如果有replace,則逐個替代
|-->foreach ($replace as $key => $val)
|-->$config[$key] = $val;
|-->return $_config[0] =& $config;   |最後返回定義的config的結果集
|-->function config_item($item)    |配置選項,從config的數祖物件中返還特殊的配置項
|-->$config =& get_config();
|-->$_config_item[$item] = $config[$item];
|-->function show_error            |用於錯誤資訊輸出
|-->$_error =& load_class('Exceptions', 'core');    |載入Exceptions類
|-->echo $_error->show_error($heading, $message, 'error_general', $status_code);  |直接輸出錯誤
|-->function show_404              |用於輸出404頁面,輸出的錯誤資訊頁面可配置
|-->function log_message           |用於寫日誌資訊
|-->$_log =& load_class('Log');
|-->$_log->write_log($level, $message, $php_error);


|-->function set_status_header     |用於輸出狀態的heade資訊
|-->function _exception_handler
|-->function remove_invisible_characters
|-->function html_escape           |過濾HTML變數
|-->return htmlspecialchars($var, ENT_QUOTES, config_item('charset'));


2.2Router路由資訊設定
|-->_set_routing() 
|-->$segments = array()    |根據目錄,控制器,函式的觸發器設定segment[]的uri段值,分別fetch()方法去取物件值
|-->include(APPPATH.'config/routes.php');       |載入config下的routes檔案
|-->$this->routes          |設定routes數祖值,從config的route中獲取
|-->$this->default_controller       |設定routes的控制器值,從config的route中獲取
|-->return $this->_validate_request($segments); |驗證uri的segment合法性
|-->$this->uri->_remove_url_suffix();$this->uri->_reindex_segments();  |進一步清理解析uri,使segment從1開始x
|-->_set_overrides()  |根據$routing的值,重新設定directory、controller、function引數
|-->$this->set_directory($routing['directory']);
|-->$this->set_class($routing['controller']);
|-->$this->set_method($routing['function']);






2.3 core/Controller.php載入
|-->__construct()                                         |建構函式
|-->self::$instance =& $this;  
|-->foreach (is_loaded() as $var => $class)       |根據is_loaded()的資訊載入相應的類
|-->$this->$var =& load_class($class);   
|-->$this->load =& load_class('Loader', 'core');  |載入core/Loader的php檔案
|-->$this->load->initialize();                    |主要用於autoload載入資訊,如libraries、database等等
|-->function &get_instance                                |返回當前例項
|-->return self::$instance


擴充套件點:PHP自動載入機制在CodeIgniter中的應用
1.PHP自動載入機制:PHP5後,提供了類的自動載入機制,即類在載入時才被使用,即Lazy loading,共有二種方式
1.1: __autoload()通過擴充套件可實現,實質為設定規則載入相應路徑的PHP檔案(require、include方式)
1.2: 將autoload_func指向php檔案,這個一般用c語言擴充套件實現 
  詳見:http://blog.csdn.net/flyingpig4/article/details/7286438

2.在CodeIgniter中的應用
根據上述原始碼分析可知:CodeIgniter中所有的操作都是以Controller為起始,只需在Cotroller載入的過程中,
使__autoload()函式自動載入即可,目前的載入方式為在application/config/config.php中設定__autoload()
函式