欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-16 16:47:10
...

解析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文件中的引导程序