ci框架原始碼解析
阿新 • • 發佈:2019-02-09
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()
函式