PHP CodeIgniter框架源碼解析
來源:程序員人生 發布時間:2014-10-20 08:00:00 閱讀次數:5587次
PHP CodeIgniter框架源碼解析
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()
函數
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈