CI框架 3.1.8 源码解析 之 index.php

时间:2021-02-14 19:58:52

解析CI源码
先上图
CI框架 3.1.8 源码解析 之 index.php
用户发起请求,当请求触达index.php时,开始初始化;
1. 设置环境常量

define('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development'); 
// 根据该常量,加载不同的配,设置不同的报错级别
// 先判断$_SERVER['CI_ENV'](可以在php.ini中指定)是否存在。
// 如果存在ENVIRONMENT就是$_SERVER['CI_ENV']的值;
// 如果不存在ENVIRONMENT就是'development'

2. 设置报错级别
php提供了16种报错级别,我们先来复习一下,报错级别吧

E_ERROR             1       致命运行错误,比如调用了未定义的函数,脚本停止运行
E_WARNING           2       警告运行错误,脚本不停止运行
E_PARSE             4       脚本解析错误,比如少个分号,逗号之类,脚本停止运行
E_NOTICE            8       通知运行错误,比如echo一个未定义的变量,脚本不停止运行
E_CORE_ERROR        16      致命初始化错误,由PHP引擎核心抛出
E_CORE_WARNING      32      警告初始化错误,由PHP引擎核心抛出
E_COMPILE_ERROR     64      致命编译时错误,由zend脚本抛出
E_COMPILE_WARNING   128     警告编译时错误,由zend脚本抛出
E_USER_ERROR        256     致命用户产生错误,用户自己使用trigger_error()产生
E_USER_WARNING      512     警告用户产生错误,用户自己使用trigger_error()产生
E_USER_NOTICE       1024    通知用户产生错误,用户自己使用trigger_error()产生
E_STRICT            2048    启用严格模式,对代码会有修改建议
E_RECOVERABLE_ERROR 4096    可被捕捉的致命错误,可以被set_error_hander定义的句柄捕获,如果没有定义该句柄,则升级为E_ERROR
E_DEPRECATED        8192    一种特殊的E_NOTICE,专门用来提示预备启用的函数
E_USER_DEPRECATED   16384   用户自己产生的E_DEPRECATED,用户自己使用trigger_error()产生
E_ALL               30719   会抛出,除 E_STRICT之外的所有错误和警告信息

源码:
switch (ENVIRONMENT)
{
   case 'development':
      error_reporting(-1); // -1等同于 E_ALL | 0表示关闭所有报错
      // error_reporting(7); 表示显示 E_ERROR(1) | E_WARING(2) | E_PARSE(4) == (1+2+4)
      ini_set('display_errors', 1); // ini_set运行时改变 php.ini配置。display_errors 配置为1表示显示博按错,为0表示不显示报错
   break;

   case 'testing':
   case 'production':
      ini_set('display_errors', 0); // 0表示不显示报错
      if (version_compare(PHP_VERSION, '5.3', '>=')) // PHP_VERSION是php的一个宏定义,存储了当前运行的php版本。version_compare用来比对版本,返回true或false
      {
         error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED); 
         // 表示 E_ALL 但除E_NOTICE、E_DEPRECATED、E_STRICT、E_USER_NOTICE、E_USER_DEPRECATED 之外的报错
      }
      else
      {
         error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_USER_NOTICE);
         // 表示 E_ALL 但除E_NOTICE、E_STRICT 、E_USER_NOTICE 之外的报错
      }
   break;

   default:
      // 503报错,环境必须配置为development、testing、production中的一种,否则报错
      header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
      echo 'The application environment is not set correctly.';
      exit(1); // EXIT_ERROR
}

3. 设置系统目录

    $system_path = 'system'; // 设置ci核心源码存放目录
    $application_folder = 'application'; // 设置用户自定义应用存放目录
    $view_folder = ''; // 用户特殊指定的view目录,未指定则默认是 application/views

    // 兼容命令行模式
    if (defined('STDIN')) // 是否定义了PHP CLI模式下的标准输入 STDIN、STDOUT、STDERR 分别是PHP CLI模式下的标准输入、标准输出和标准错误流
    {
        chdir(dirname(__FILE__)); // 把php CLI脚本的运行目录,指定为当前目录
    }

    if (($_temp = realpath($system_path)) !== FALSE) // realpath返回变量的绝对路径
    {
        $system_path = $_temp.DIRECTORY_SEPARATOR; 
        // DIRECTORY_SEPARATOR为目录分隔符及'/' 
        // 将system_path设置为绝对路径
    }
    else
    {
        // 确保绝对路径正确
        // 假设当前为linux环境,这里的'/\\'表示 linux文件分隔符(/) windows文件分隔符(\)
        $system_path = strtr( 
            rtrim($system_path, '/\\'),// 代码的意思是$system_path 从右往左看,将所有出现的/或\删除,直到遇见不为/或\的字符时停止。
            '/\\', // strtr 会同时匹配 /\ 、 / 、 \ 三种情况
            DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR // 不仅会替换 /\为 //,还会替换\为/
        ).DIRECTORY_SEPARATOR; // 最后连接字符 '/' 
    }

    // Is the system path correct?
    if ( ! is_dir($system_path))
    {
        // 报503,路径不存在
        header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
        echo 'Your system folder path does not appear to be set correctly. Please open the following file and correct this: '.pathinfo(__FILE__, PATHINFO_BASENAME);
        exit(3); // EXIT_CONFIG
    }

4.设置应用文件目录

    // 定义SELF常量为,当前文件名
    define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME)); 

    // 定义BASEPATH常量为,系统文件的目录
    define('BASEPATH', $system_path);

    // Path to the front controller (this file) directory
    define('FCPATH', dirname(__FILE__).DIRECTORY_SEPARATOR); // 定义FCPATH常量为,这个当前文件的目录

    // 定义SYSDIR常量为,系统文件的名字
    define('SYSDIR', basename(BASEPATH));

    // 指定application的目录
    if (is_dir($application_folder))  
    // 还记得前面定义的$application_folder吗? 这里是检查$application_folder变量,是否符合目录格式
    {
        if (($_temp = realpath($application_folder)) !== FALSE) // 与system相同
        {
            $application_folder = $_temp;
        }
        else
        {
            $application_folder = strtr(
                rtrim($application_folder, '/\\'),
                '/\\',
                DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
            );
        }
    }
    elseif (is_dir(BASEPATH.$application_folder.DIRECTORY_SEPARATOR)) 
    // 如果$application_folder不符合目录格式,则判断 $system_path.$application_folder.DIRECTORY_SEPARATOR 是否符合目录格式
    {
        $application_folder = BASEPATH.strtr( // 取$system_path作为application的目录
            trim($application_folder, '/\\'),
            '/\\',
            DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
        );
    }
    else
    {
        // 文件不存在
        header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
        echo 'Your application folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;
        exit(3); // EXIT_CONFIG
    }
    define('APPPATH', $application_folder.DIRECTORY_SEPARATOR); // 定义常量APPPATH为,应用目录

4.设置视图层目录

    // The path to the "views" directory
    if ( ! isset($view_folder[0]) && is_dir(APPPATH.'views'.DIRECTORY_SEPARATOR)) 
    // view_folder是否不为数组
    {
        $view_folder = APPPATH.'views';
    }
    elseif (is_dir($view_folder)) //$view_folder也可以配置为一个相对目录
    {
        if (($_temp = realpath($view_folder)) !== FALSE)
        {
            $view_folder = $_temp;
        }
        else
        {
            $view_folder = strtr(
                rtrim($view_folder, '/\\'),
                '/\\',
                DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
            );
        }
    }
    elseif (is_dir(APPPATH.$view_folder.DIRECTORY_SEPARATOR))
    {
        $view_folder = APPPATH.strtr(
            trim($view_folder, '/\\'),
            '/\\',
            DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
        );
    }
    else
    {
        header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
        echo 'Your view folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;
        exit(3); // EXIT_CONFIG
    }

    define('VIEWPATH', $view_folder.DIRECTORY_SEPARATOR); // 定义视图文件常量

5.执行引导程序

require_once BASEPATH.'core/CodeIgniter.php'; // 运行system文件中的引导程序