CodeIgniter初尝试
最近尝试用CodeIgniter做一个博客程序,刚起步,打算作为进军CI的一个试验品。
CodeIgniter以轻量级著称,所以,功能上应该比较容易上手的。
一、CodeIgniter的运行流程,都在core/CodeIgniter.php中
<?php //定义版本 define('CI_VERSION', '2.0.3'); //定义分支 define('CI_CORE', FALSE); //加载基础函数库 require(BASEPATH.'core/Common.php'); //加载框架常量 if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php')) { require(APPPATH.'config/'.ENVIRONMENT.'/constants.php'); } else { require(APPPATH.'config/constants.php'); } //错误处理 set_error_handler('_exception_handler'); if ( ! is_php('5.3')) { @set_magic_quotes_runtime(0); // Kill magic quotes } //获取设定的子类前缀,这个子类是指继承核心类的子类 if (isset($assign_to_config['subclass_prefix']) AND $assign_to_config['subclass_prefix'] != '') { get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix'])); } //设定页面超时 if (function_exists("set_time_limit") == TRUE AND @ini_get("safe_mode") == 0) { @set_time_limit(300); } //加载计时类,开始计时 $BM =& load_class('Benchmark', 'core'); $BM->mark('total_execution_time_start'); $BM->mark('loading_time:_base_classes_start'); //加载hook(钩子)类 $EXT =& load_class('Hooks', 'core'); //钩子 $EXT->_call_hook('pre_system'); //加载配置管理类 $CFG =& load_class('Config', 'core'); // Do we have any manually set config items in the index.php file? if (isset($assign_to_config)) { $CFG->_assign_to_config($assign_to_config); } //utf8类 $UNI =& load_class('Utf8', 'core'); //URI $URI =& load_class('URI', 'core'); //路由 $RTR =& load_class('Router', 'core'); $RTR->_set_routing(); // Set any routing overrides that may exist in the main index file if (isset($routing)) { $RTR->_set_overrides($routing); } //核心输出类 $OUT =& load_class('Output', 'core'); //判断是否有缓存,有则直接输出缓存并结束 if ($EXT->_call_hook('cache_override') === FALSE) { if ($OUT->_display_cache($CFG, $URI) == TRUE) { exit; } } //安全类 $SEC =& load_class('Security', 'core'); //输入类 $IN =& load_class('Input', 'core'); //语言 $LANG =& load_class('Lang', 'core'); //加载基础模块类,有继承子类则同时加载 //这个是我自己加上的,下面说到模块时再讲为什么写到这里 require BASEPATH.'core/Model.php'; if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Model.php')) { require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Model.php'; } //加载基础控制类,有继承子类则同时加载 require BASEPATH.'core/Controller.php'; function &get_instance() { return CI_Controller::get_instance(); } if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php')) { require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'; } // 加载当前控制器 if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php')) { show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'); } include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'); //记录 $BM->mark('loading_time:_base_classes_end'); //安全检查 $class = $RTR->fetch_class(); $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'))) ) { show_404("{$class}/{$method}"); } //Hook,构造控制器前 $EXT->_call_hook('pre_controller'); //构造控制器 // Mark a start point so we can benchmark the controller $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start'); $CI = new $class(); //Hook, 执行动作前 $EXT->_call_hook('post_controller_constructor'); //最关键一步,执行动作,如果控制器内有_remap方法,则将动作交与_remap // Is there a "remap" function? If so, we call it instead if (method_exists($CI, '_remap')) { $CI->_remap($method, array_slice($URI->rsegments, 2)); } else { // 404错误处理 if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI)))) { // Check and see if we are using a 404 override and use it. if ( ! empty($RTR->routes['404_override'])) { $x = explode('/', $RTR->routes['404_override']); $class = $x[0]; $method = (isset($x[1]) ? $x[1] : 'index'); if ( ! class_exists($class)) { if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) { show_404("{$class}/{$method}"); } include_once(APPPATH.'controllers/'.$class.'.php'); unset($CI); $CI = new $class(); } } else { show_404("{$class}/{$method}"); } } //调用动作 call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2)); } // Mark a benchmark end point $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end'); //Hook $EXT->_call_hook('post_controller'); //Hook if ($EXT->_call_hook('display_override') === FALSE) { $OUT->_display(); } //Hook $EXT->_call_hook('post_system'); //关闭数据库连接 if (class_exists('CI_DB') AND isset($CI->db)) { $CI->db->close(); } /* 文件结束 */
二、核心类继承(扩展Model)
在程序文件夹/core/中定义用于继承扩展核心库的类,如果定义了类名同CI库相同,则覆盖核心库的相应类,否则使用MY_或在配置文件内定义的前缀作为前缀定义类去继承核心类。这里最常用到的是扩展CI_Model和CI_Controller,方便在不修改核心文件的情况下,对同一个程序内部作初始化,或扩展常用操作。
这里我遇到的问题是,扩展了CI_Model类,但扩展类构造函数使用了一个表名称的参数,类似下面这样:
<?php class MY_Model extends CI_Model { protected $tbl; function __construct($tablename){ parent::__construct(); $this->tbl=$tablename; } #... } //
结果在运行程序时出现参数错误,经追查,发现是在实例化模型时,由系统通过loadClass函数加载了基础Model类,而loadClass函数在加载类的同时,会实例化一个唯一的类实例,这里实例化的时候当然没有传入参数,所以导致参数错误。其实模块基础类根本没有实例化的需要,所以,我就在加载控制器基础类之前,加了几行以加载基础模块类,这样,后面实例模块的时候,检测到模块基础类已经加载,就不会通过loadClass来加载了。
暂时先记录这些,以后使用过程中有疑问再另行记录