CodeIgniter框架——源码分析之CodeIgniter.php
CodeIgniter.php可以说是CI的核心,大部分MVC的流程都是在这个文件夹中处理的,其中加载了很多外部文件,完成CI的一次完整流程。
首先是定义了CI的版本(此处为CI 2.2.0),接下来是连续require了2个文件,core/Common.php,config/constants.php,接下来是设置错误处理。
注:
CI的生命周期——system/core/CodeIgniter.php
include('core/commons.php')
载入 config/constant.php
其他配置
load benchmark,hooks
hook: pre_system
load Config, Utf8, URI, Router, Output
hook: cache_override
- output::_display_cache()
load Security, Input, Lang
hook: pre_controller
$CI = new $class()
hook: post_controller_constructor
hook: post_controller
hook: display_override
- Output::_display()
hook: post_system
清理数据库连接
源码分析如下:
<?php
/**
* 详见 http://www.phpddt.com/tag/codeIgniter/
*/
//如果入口文件系统目录常量BASEPATH没定义,就挂了
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
//定义常量:CI_VERSION,CI_CORE
define('CI_VERSION', '2.2.0');
define('CI_CORE', FALSE);
/*
*引入系统目录下core/Common.php,这里面全是CI的系统全局函数如is_php()、load_class()等
*/
require(BASEPATH.'core/Common.php');
/*
*加载应用目录下的常量,注意如果存在相应的开发环境目录,则加载对应目录下的文件,ENVIRONMENT实在入口文件定义的
*/
if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))
{
require(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
}
else
{
require(APPPATH.'config/constants.php');
}
/*
*_exception_handler函数是刚才在Common.php中加载的函数,用来拦截错误,记录日志,
* set_error_handler是在_exception_handler函数中用load_class加载过来的。
*/
set_error_handler('_exception_handler');
//关闭magic quotes,关于这个的详细介绍请看:http://www.phpddt.com/php/php-magic-quotes.html
if ( ! is_php('5.3'))
{
@set_magic_quotes_runtime(0); // Kill magic quotes
}
/*
*子类前缀,很重要,也就是说你可以去扩展CI的核心类,后面说,默认配置应该是MY_
*/
//看看你在index.php中是否定义前缀,没有定义的话就加载配置文件获知,get_config是Common.php中的全局函数
if (isset($assign_to_config['subclass_prefix']) AND $assign_to_config['subclass_prefix'] != '')
{
get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));
}
/*
*php 程序运行默认是30s,这里用set_time_limt延长了,关于set_time_Limit() http://www.phpddt.com/php/set_time_limit.html
* 扩展阅读,关于safe_mode:http://www.phpddt.com/php/643.html ,你会完全明白的
*/
if (function_exists("set_time_limit") == TRUE AND @ini_get("safe_mode") == 0)
{
@set_time_limit(300);
}
/*
* 加载Benchmark,它很简单,就是计算任意两点之间程序的运行时间
*/
$BM =& load_class('Benchmark', 'core');
$BM->mark('total_execution_time_start');
$BM->mark('loading_time:_base_classes_start');
//加载钩子,后期会分析到,这玩意特好,扩展它能改变CI的运行流程
$EXT =& load_class('Hooks', 'core');
//这里就是一个钩子啦,其实就是该钩子程序在这里执行
$EXT->_call_hook('pre_system');
//加载配置文件,这里面都是一些加载或获取配置信息的函数
$CFG =& load_class('Config', 'core');
// 如果在index.php中也有配置$assign_to_config,则也把它加入到$CFG
if (isset($assign_to_config))
{
$CFG->_assign_to_config($assign_to_config);
}
//加载utf8组件、URI组件、Router组件
$UNI =& load_class('Utf8', 'core');
$URI =& load_class('URI', 'core');
$RTR =& load_class('Router', 'core');
$RTR->_set_routing();
//如果在index.php中定义了$routing,那么就会覆盖上面路由
if (isset($routing))
{
$RTR->_set_overrides($routing);
}
//加载output输出组件,不然你怎么用$this->Load->view()啊
$OUT =& load_class('Output', 'core');
//又见钩子,这里你可以自己写钩子程序替代Output类的缓存输出
if ($EXT->_call_hook('cache_override') === FALSE)
{
if ($OUT->_display_cache($CFG, $URI) == TRUE)
{
exit;
}
}
//安全组件啦,防xss攻击啊,csrf攻击啊
//关于xss攻击:http://www.phpddt.com/php/php-prevent-xss.html
//关于csrf:攻击:http://www.phpddt.com/reprint/csrf.html
$SEC =& load_class('Security', 'core');
//加载输入组件,就是你常用的$this->input->post();等
$IN =& load_class('Input', 'core');
//加载语言组件啦
$LANG =& load_class('Lang', 'core');
//引入CI的控制器父类
require BASEPATH.'core/Controller.php';
function &get_instance()
{
return CI_Controller::get_instance();
}
//当然你扩展了CI_Controller控制器的话,也要引入啦
if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
{
require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
}
//加载你自己应用中的控制器Controller,如果没有当然error啦
//$RTR就是Router类的实例,Router类在构造实例的时候已经对请求的URL进行了解析,并得出对应的类名和方法名,下面就是通过fetch_class方法来获得对应的类名,如果这个控制器的文件存在,就加载这个文件,否则就报错。
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');
// 好的基础的类都加载完毕了,咱可以mark一下
$BM->mark('loading_time:_base_classes_end');
//路由获取了控制器名和方法名,比如说默认welcome/index
$class = $RTR->fetch_class();
$method = $RTR->fetch_method();
//这里CI规定一般非公共的方法以_开头,下面是判断,如果URI不可访问就show_404(),这个404响应的页面也是CI自定义的,show_404()函数可以在Common.php中找到
if ( ! class_exists($class)
OR strncmp($method, '_', 1) == 0
OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
)
{
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');
}
}
else
{
show_404("{$class}/{$method}");
}
}
//又是钩子,该钩子发生在控制器实例化之前的
$EXT->_call_hook('pre_controller');
//又mark一个点
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');
//终于实例化控制器了
$CI = new $class();
//钩子,不想多说了
$EXT->_call_hook('post_controller_constructor');
/*
* ------------------------------------------------------
* Call the requested method
* ------------------------------------------------------
*/
// 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
{
// is_callable() returns TRUE on some versions of PHP 5 for private and protected
// methods, so we'll use this workaround for consistent behavior
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}");
}
}
// 终于调用方法了,$this->load->view()把内容放到缓存区
call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
}
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');
$EXT->_call_hook('post_controller');
//这里就是把缓存区的内容输出了
if ($EXT->_call_hook('display_override') === FALSE)
{ $OUT->_display();
}
//调用post_system的hook
$EXT->_call_hook('post_system');
//关闭数据库的链接
if (class_exists('CI_DB') AND isset($CI->db))
{
$CI->db->close();
}
CodeIgniter框架——源码分析之CodeIgniter.php的更多相关文章
- CodeIgniter框架——源码分析之入口文件index.php
CodeIgniter框架的入口文件主要是配置开发环境,定义目录常量,加载CI的核心类core/CodeIgniter.php. 在index.php中,CI首先做的事情就是设置PHP的错误报告, ...
- CodeIgniter框架——源码分析之Config.php
CI框架的配置信息被存储在$config数组中,我们可以添加自己的配置信息或配置文件到$config中: $this->config->load('filename'); //加载配置文件 ...
- 介绍开源的.net通信框架NetworkComms框架 源码分析
原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 售价249英镑 我曾经花了 ...
- Android Small插件化框架源码分析
Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...
- YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)
YII 框架源码分析 百度联盟事业部——黄银锋 目 录 1. 引言 3 1.1.Yii 简介 3 1.2.本文内容与结构 3 2.组件化与模块化 4 2.1.框架加载和运行流程 4 ...
- Spark RPC框架源码分析(一)简述
Spark RPC系列: Spark RPC框架源码分析(一)运行时序 Spark RPC框架源码分析(二)运行时序 Spark RPC框架源码分析(三)运行时序 一. Spark rpc框架概述 S ...
- Spark RPC框架源码分析(二)RPC运行时序
前情提要: Spark RPC框架源码分析(一)简述 一. Spark RPC概述 上一篇我们已经说明了Spark RPC框架的一个简单例子,Spark RPC相关的两个编程模型,Actor模型和Re ...
- Spark RPC框架源码分析(三)Spark心跳机制分析
一.Spark心跳概述 前面两节中介绍了Spark RPC的基本知识,以及深入剖析了Spark RPC中一些源码的实现流程. 具体可以看这里: Spark RPC框架源码分析(二)运行时序 Spark ...
- nodejs的Express框架源码分析、工作流程分析
nodejs的Express框架源码分析.工作流程分析 1.Express的编写流程 2.Express关键api的使用及其作用分析 app.use(middleware); connect pack ...
随机推荐
- 转:从零开始做app需要做的事情列表
https://qdan.me/list/VaXl7N8emfv1ayWg 从零开始做App的Bootstrap 做一个App,需要很多东西. 不定期更新. 团队 工欲善其事,必先利其器. 需求管理 ...
- CHAPTER ONE LOAD-BALANCING
1.1 Synopsis In this part, we will explain how to create a load-balancer withnginxfor a lot of OpenE ...
- 【Python3 爬虫】01_简单页面抓取
运行平台:Winodows 10 Python版本:Python 3.4.2 IDE:Sublime text3 网络爬虫 网络爬虫,也叫网络蜘蛛(Web Spider),如果把互联网比喻成一个蜘蛛网 ...
- ijkPlayer 集成
代码地址如下:http://www.demodashi.com/demo/11957.html 概述 ijkplayer 是一款做视频直播的框架,基于FFmpeg,支持Android和iOS.这里介绍 ...
- mongoDB 高级查询之复杂查询$where
http://blog.csdn.net/drifterj/article/details/7833883
- 【MyBatis学习07】动态sql
1. 动态sql 动态sql是mybatis中的一个核心,什么是动态sql?动态sql即对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接.组装.就拿上一篇博文中对用户的综合查询一例来 ...
- 冲销会计凭证:FBRP与FB08的区别
FBRA一般是用来对已经清帐的凭证进行冲销的,我们知道普通的冲销只要用FB08就可以了,但是对于已经被清帐和凭证,我们只能用FBRA来进行清帐,我们来按以下的没测试来做验证一下.STEP1:用F-22 ...
- 电脑 F键(功能键)的具体作用
F1:如果你处在一个选定的程序中而需要帮助,那么请按下F1.如果现在不是处在任何程序中,而是处在资源管理器或桌面,那么按下F1就会出现Windows的帮助程序.如果你正在对某个程序进行操作,而想得到W ...
- Arthas安装问题
1. 下载安装 方式一: 安装Arthas: curl -L https://alibaba.github.io/arthas/install.sh | sh 启动Arthas: ./as.sh 报t ...
- 网页CSS font-size使用em替代px
px和em都是长度单位,区别是,px的值是固定的,em的值是相对的,并且em会继承父级元素的字体大小. 任意浏览器的默认字体高都是16px.所以未经调整的浏览器都符合: 1em=16px.那么12px ...