CI框架源码解析一之入口文件index.php

        Index.php作为CI框架的入口文件,源码分析,自然而然由此开始。在源码分析的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现,如果英文水平很好的话,读过index.php文件的英文注释之后也就基本明白了inde.php都做了些什么。本来想第一篇写解析CI框架的目录结构的,像这一般网上一搜都是一大堆,也就放弃了这个想法。博主是基于CodeIgniter-v3.1.0最新版本进行解读分析。ok,书归正传,在博主看来CI框架的index.php文件一共完成了四项工作:

① 设置框架应用的环境状态

② 配置系统、应用、视图等程序目录以及得到其路径

③ 系统、应用、视图等目录的正确性验证

④ 载入 core/CodeIgniter.php框架核心文件,启动框架

1、设置框架应用的环境状态

define('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development');

        这里的development可以是任何你喜欢的环境名称(比如working,再如debug),相对应的,你要在下面的switch case代码块中,对设定的环境做相关的错误等级控制。(CI框架设置了三种应用场景状态,分别是:development(开发),testing(测试),production(产品)。development(开发)状态,也就是默认的状态下会产生错误报告,testing(测试),production(产品)状态下则不会产生错误报告)否则,CI框架会认为你没有配置好相应的环境,从而退出进程并给出对应的错误信息:

    default:
        //header() 被用来发送自定义的 HTTP 报文。关于HTTP报文的更多信息请参考php手册
        header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
        echo 'The application environment is not set correctly.';
        exit(1); 

        之所以一定要配置配置ENVIRONMENT?这是因为,CI框架中很多组件都依赖于ENVIRONMENT的配置,例如,查看system/config/Common.php, 这其中有一段引入配置文件的代码,是这样实现的:

    if (file_exists(APPPATH . 'config/' . ENVIRONMENT . '/mimes.php')) {
        $_mimes = include(APPPATH . 'config/' . ENVIRONMENT . '/mimes.php');
    } elseif (file_exists(APPPATH . 'config/mimes.php')) {
        $_mimes = include(APPPATH . 'config/mimes.php');
    } else {
        $_mimes = array();
    }

        在CI框架中,很多配置文件都是通过这种方式引入的,因此ENVRIONMENT对于CI框架的正确运行时必须的,所以需要在开始的时候配置好ENVIRONMENT。设置ENVIRONMENT的一个好处是:可以很方便的切换系统的配置而不必修改系统代码。例如,在系统进入测试阶段时,database配置为测试的数据库,而在系统测试完毕时,database切换到线上的数据库。这好比是用一个开关控制了系统的环境切换,自然是非常方便的。

2、配置系统、应用、视图等程序目录以及得到其路径

        CI框架允许你将系统核心源码和应用程序代码进行分开放置,但是你必须设定好系统的system文件夹和application文件夹(同样,文件夹名字可以是任何合法的文件夹名称,而不一定使用’system’和’application’)的名称、路径等信息:

    //定义系统目录名称
    $system_path = 'system';
    
    //定义你的应用目录名称
    $application_folder = 'application';
    
    //视图文件存放目录
    //如果要将视图目录移到应用程序目录,则设置在此处的路径。如果空白,它将默认为您的应用程序目录中的标准位置。
    $view_folder = '';

        下面有这样一段代码,然后很多人就不明白为什么要放这样几句代码了,在这里特别说明一下:

    if (defined('STDIN')) {
        //chdir函数用来改变目录
        chdir(dirname(__FILE__));
    }

        这段代码主要是用来干嘛的呢?首先,STDIN、STDOUT、STDERR是PHP以 CLI(Command Line Interface)模式运行而定义的三个常量,这三个常量类似于Shell的stdin,stdout,stdout,分别是PHP CLI模式下的标准输入、标准输出和标准错误流。也就是说,这三行代码是为了保证命令行模式下,CI框架可以正常运行。

3、系统、应用、视图等目录的正确性验证

1) 系统(system)文件目录的正确性验证

    //得到规范化的绝对路径名
    //此段代码用于判断生成system系统文件目录
    if (($_temp = realpath($system_path)) !== FALSE) {
        //$system_path就是当前你的CI框架核心文件所存放的绝对路径名
        $system_path = $_temp . DIRECTORY_SEPARATOR;
    } else {
        $system_path = strtr(rtrim($system_path, '/\\'), '/\\', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
    }
    
    //如果$system_path所指向的文件目录不存在,则die
    if (!is_dir($system_path)) {
        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
    }

2) 应用(application)文件目录的正确性验证

    //此段代码用于判断生成application应用文件目录
    if (is_dir($application_folder)) {
        if (($_temp = realpath($application_folder)) !== FALSE) {
            $application_folder = $_temp;
        } else {
            $application_folder = strtr(rtrim($application_folder, '/\\'), '/\\', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR);
        }
    } elseif (is_dir(BASEPATH . $application_folder . DIRECTORY_SEPARATOR)) {
        $application_folder = BASEPATH . strtr(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);
    }

3) 视图(view)文件目录的正确性验证

    //此段代码用于判断生成view视图文件目录
    if (!isset($view_folder[0]) && is_dir(APPPATH . 'views' . DIRECTORY_SEPARATOR)) {
        $view_folder = APPPATH . 'views';
    } elseif (is_dir($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);
    }

        几个定义的常量(PATH结尾的常量表示目录路径,DIR结尾的变量表示目录名):

    //SELF(这里指index.php文件)
    define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));
    //BASEPATH(system文件夹的路径)
    define('BASEPATH', $system_path);
    //FCPATH(前端控制器的路径)
    define('FCPATH', dirname(__FILE__) . DIRECTORY_SEPARATOR);
    //SYSDIR(系统system目录名)
    define('SYSDIR', basename(BASEPATH));
    //APPPATH(应用程序路径)
    define('APPPATH', $application_folder . DIRECTORY_SEPARATOR);
    //VIEWPATH(视图目录路径)
    define('VIEWPATH', $view_folder . DIRECTORY_SEPARATOR);

       注:查看所有常量的方法:

    var_dump(get_defined_constants());

4、载入 core/CodeIgniter.php框架核心文件,启动框架

       入口文件的最后一行,引入CodeIgniter.php框架核心文件(也是下一步框架执行的关键)。CodeIgniter.php被称为bootstrap file,也就是它是一个引导文件,是CI框架执行流程的核心文件。

    //最后就是加载CI框架的核心引导文件了
    require_once BASEPATH . 'core/CodeIgniter.php';

        总结一下,index.php并没有做太多复杂的工作,而是类似军队中押运粮草的,兵马未动粮草先行,为CI框架的运行提供了一系列配置参数和正确性验证,而这些配置和验证,是CI框架能够正常运行的关键。

        最后,贴一下整个index.php文件的源码(注释版):

    =')) {
                error_reporting(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);
            }
            break;
    
        default:
            //header() 被用来发送自定义的 HTTP 报文。关于HTTP报文的更多信息请参考php手册
            header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
            echo 'The application environment is not set correctly.';
            exit(1); // EXIT_ERROR
    }
    
    /**
     * 定义系统目录名称
     * 此变量必须包含您的“系统”目录的名称。如果它不在与此文件相同的目录中,则设置路径。
     * 里面存放的是CI框架的各种核心文件。
     */
    $system_path = 'system';
    
    /**
     * 定义你的应用目录名称
     * 如果你希望此前控制器使用不同的“应用程序”目录,而不是默认的“应用程序”目录,你可以在这里设置它的名称。
     */
    $application_folder = 'application';
    
    /**
     * 视图文件存放目录
     * 如果要将视图目录移到应用程序目录,则设置在此处的路径。如果空白,它将默认为您的应用程序目录中的标准位置。
     */
    $view_folder = '';
    
    
    // --------------------------------------------------------------------
    // END OF USER CONFIGURABLE SETTINGS.  DO NOT EDIT BELOW THIS LINE
    //用户可配置设置的结束。不要在这条线下编辑
    //这里只是CI框架进行一下提示,如果你想改动的话,还是可以的
    // --------------------------------------------------------------------
    
    
    //设置正确的目录
    /**
     * STDIN、STDOUT、STDERR是PHP以 CLI(Command Line Interface)模式运行而定义的三个常量,
     * 这三个常量类似于Shell的stdin,stdout,stdout,分别是PHP CLI模式下的标准输入、标准输出和标准错误流。
     * 也就是说,这三行代码是为了保证命令行模式下,CI框架可以正常运行。
     */
    if (defined('STDIN')) {
        //chdir函数用来改变目录
        chdir(dirname(__FILE__));
    }
    //得到规范化的绝对路径名
    //此段代码用于判断生成system系统文件目录
    if (($_temp = realpath($system_path)) !== FALSE) {
        //$system_path就是当前你的CI框架核心文件所存放的绝对路径名
        $system_path = $_temp . DIRECTORY_SEPARATOR;
    } else {
        $system_path = strtr(
                rtrim($system_path, '/\\'),
                '/\\',
                DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR
            ) . DIRECTORY_SEPARATOR;
    }
    
    //如果$system_path所指向的文件目录不存在,则die
    if (!is_dir($system_path)) {
        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
    }
    
    /**
     * 下面主要是设置各种主要的常量
     */
    //当前文件名称,也就是“index.php”
    //pathinfo()函数返回文件路径的信息
    define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));
    
    //system文件的绝对路径
    define('BASEPATH', $system_path);
    
    //项目文件目录的绝对路径
    //dirname()函数返回路径中的目录部分
    define('FCPATH', dirname(__FILE__) . DIRECTORY_SEPARATOR);
    
    // system文件夹名称“system”
    //basename()函数返回路径中的文件名部分
    define('SYSDIR', basename(BASEPATH));
    
    //此段代码用于判断生成application应用文件目录
    if (is_dir($application_folder)) {
        if (($_temp = realpath($application_folder)) !== FALSE) {
            $application_folder = $_temp;
        } else {
            $application_folder = strtr(
                rtrim($application_folder, '/\\'),
                '/\\',
                DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR
            );
        }
    } elseif (is_dir(BASEPATH . $application_folder . DIRECTORY_SEPARATOR)) {
        $application_folder = BASEPATH . strtr(
                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
    }
    //application应用目录的绝对路径
    define('APPPATH', $application_folder . DIRECTORY_SEPARATOR);
    
    //此段代码用于判断生成view视图文件目录
    if (!isset($view_folder[0]) && is_dir(APPPATH . 'views' . DIRECTORY_SEPARATOR)) {
        $view_folder = APPPATH . 'views';
    } elseif (is_dir($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
    }
    //view视图目录的绝对路径
    define('VIEWPATH', $view_folder . DIRECTORY_SEPARATOR);
    
    //最后就是加载CI框架的核心引导文件了
    require_once BASEPATH . 'core/CodeIgniter.php';

你可能感兴趣的:(CodeIgniter,CodeIgniter源码解析)