1. 程式人生 > >CI框架原始碼解析一之入口檔案index.php

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檔案的原始碼(註釋版):

    <?php
    
    /**
     * =======================================
     * Created by Pocket Knife Technology.
     * User: ZhiHua_W
     * Date: 2016/10/14 0020
     * Time: 下午 2:14
     * Project: CodeIgniter框架—原始碼分析
     * Power: Analysis for Index.php
     * =======================================
     */
    
    /**
     * 框架的第一步就是定義框架程式碼當前的使用場景狀態
     * 一共有development(開發),testing(測試),production(產品)三個場景狀態
     * 不同的場景狀態將會產生不同級別的錯誤報告
     */
    define('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development');
    
    /**
     * 這裡就會對場景狀態進行判斷
     * development(開發)狀態,也就是預設的狀態下會產生錯誤報告
     * testing(測試),production(產品)狀態下則不會產生錯誤報告
     */
    switch (ENVIRONMENT) {
        case 'development':
            //error_reporting()函式是php的內建函式,用來設定php的報錯級別並返回當前級別
            //函式語法:
            //error_reporting(report_level) report_level引數是錯誤等級,一共有已下幾種:
            //值 常量 描述
            //1 E_ERROR 致命的執行錯誤。錯誤無法恢復,暫停執行指令碼
            //2 E_WARNING 執行時警告(非致命性錯誤)。非致命的執行錯誤,指令碼執行不會停止
            //4 E_PARSE 編譯時解析錯誤。解析錯誤只由分析器產生
            //8 E_NOTICE 執行時提醒(這些經常是你程式碼中的bug引起的,也可能是有意的行為造成的。)
            //16 E_CORE_ERROR PHP啟動時初始化過程中的致命錯誤
            //32 E_CORE_WARNING PHP啟動時初始化過程中的警告(非致命性錯)。
            //64 E_COMPILE_ERROR 編譯時致命性錯。這就像由Zend指令碼引擎生成了一個E_ERROR
            ///128 E_COMPILE_WARNING 編譯時警告(非致命性錯)。這就像由Zend指令碼引擎生成了一個E_WARNING警告
            //256 E_USER_ERROR 使用者自定義的錯誤訊息。這就像由使用PHP函式trigger_error(程式設計師設定E_ERROR)
            //512 E_USER_WARNING 使用者自定義的警告訊息。這就像由使用PHP函式trigger_error(程式設計師設定的一個E_WARNING警告)
            //1024 E_USER_NOTICE 使用者自定義的提醒訊息。這就像一個由使用PHP函式trigger_error(程式設計師一個E_NOTICE集)
            //2048 E_STRICT 編碼標準化警告。允許PHP建議如何修改程式碼以確保最佳的互操作性向前相容性
            //4096 E_RECOVERABLE_ERROR 開捕致命錯誤。這就像一個E_ERROR,但可以通過使用者定義的處理捕獲(又見set_error_handler())
            //8191 E_ALL 所有的錯誤和警告(不包括 E_STRICT) (E_STRICT will be part of E_ALL as of PHP 6.0)
            //更為具體的用法大家可以查詢php手冊
            error_reporting(-1);
    
            //ini_set用來設定php.ini的值,在函式執行的時候生效,指令碼結束後,設定失效。
            //無需開啟php.ini檔案,就能修改配置,對於虛擬空間來說,很方便。
            //不是所有的引數都可以配置,可以檢視手冊中的列表。
            //可以使用ini_get來獲取所設定的值,例如:echo ini_get('display_errors');
            ini_set('display_errors', 1);
    
            break;
    
        case 'testing':
        case 'production':
            ini_set('display_errors', 0);
    
            //version_compare() 用於對比兩個「PHP 規範化」的版本數字字串。 這對於編寫僅能相容某些版本 PHP 的程式很有幫助。
            if (version_compare(PHP_VERSION, '5.3', '>=')) {
                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';

相關推薦

CI框架原始碼解析入口檔案index.php

        Index.php作為CI框架的入口檔案,原始碼分析,自然而然由此開始。在原始碼分析的過程中,我們並不會逐行進行解釋,而只解釋核心的功能和實現,如果英文水平很好的話,讀過index.php檔案的英文註釋之後也就基本明白了inde.php都做了些什麼。本來

CI框架原始碼解析引導檔案CodeIgniter.php

         上篇解析入口檔案寫到載入 core/CodeIgniter.php框架核心檔案,啟動框架。CodeIgniter.php檔案被稱為BOOTSTRAP,也就是引導檔案,這裡也就是CI框架的核心了。其實把CodeIgniter.php這個檔案的程式碼執行一

CI框架原始碼解析】分頁類檔案Pagination.php

<?php /** * ======================================= * Created by Pocket Knife Technology. * User: ZhiHua_W * Date: 2016/11/08 0

CI框架學習--隱藏入口檔案-index.php

一般CI框架第一次使用時: 原地址為: http://127.0.0.1/CI/index.php/hello/index  隱藏入口檔案後只需要把地址寫成即可: http://127.0.0.1/CI/hello/index 1、需要開啟Apache的 rew

Elastic-Job原始碼解析()與Spring完美整合

看過小編寫SpringFramework原始碼解析的同學應該對Spring支援自定義標籤還有點印象吧,沒有的話我們回顧下,然後看看Elastic-Job是如何巧妙的利用自定義標籤生成Job任務的吧。請注意這裡用了一個巧妙關鍵字。我們看它如何巧妙的吧。 Spring自定義

ci框架原始碼解析

1.index.php :入口檔案|-->define('ENVIRONMENT')  |主要用於設定errors日誌輸出級別|-->$system_path |設定系統路徑|-->設定BASEPATH、FCPATH、SYSDIR、APPPATH等    

CI框架隱藏入口檔案index.php

1、修改 apache 配置檔案conf/httpd.conf 或者 httpd-vhost.conf開啟重寫模組 LoadModule rewrite_module modules/mod_rewrite.soAllowOverride None 修改為 AllowOver

【opencart3原始碼分析】入口檔案index.php

<?php // 定義版本號 define('VERSION', '3.1.0.0_a1'); // 載入配置檔案 if (is_file('config.php')) { require_once('config.php'); } // 安裝 if (!def

ThinkPHP5.X PHP5.6.27-nts + Apache 通過 URL 重寫來隱藏入口檔案 index.php

我們先來看看官方手冊給出關於「URL 重寫」的參考: 可以通過 URL 重寫隱藏應用的入口檔案 index.php ,Apache 的配置參考: 1、http.conf 配置檔案載入 mod_rewrite.so 模組2、AllowOverride Node 中將 None 改為 All3、將下

Nginx配置 隱藏入口檔案index.php

Nginx配置檔案裡放入這段程式碼 server { location / { index index.php index.html index.htm l.php; autoindex on; if (!-e $request_

tp5隱藏入口檔案index.php,開發環境是Lamp

因為專案需要,我們要注意專案的安全性,同時tp5的url過長,所以我們要隱藏入口檔案index.php 舉例說明:www.xxx.com/tp5(專案名稱)/public/index.php/模組名/控制器名/方法名,這是一般的url訪問地址。 隱藏後:http://xxx.com/tp5/

TP5 隱藏入口檔案 index.php

找到public下的.htaccess <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d Re

TP5如何隱藏入口檔案index.php

一、Apache 在ThinkPHP5.0中,出於優化的URL訪問原則,還支援通過URL重寫隱藏入口檔案,下面以Apache為例說明隱藏應用入口檔案index.php的設定。 下面是Apache的配置過程,可以參考下: 1、httpd.conf配置檔案中載入了mod_rewr

ubuntu-apache下隱藏thinkphp入口檔案index.php

1、首先開啟apache的rewirte模組       修改/etc/apache2/apache2.conf檔案,把AllowOverride None改為AllowOverride All 2、在專案根目錄下新增.htaccess檔案,修改rewrite規則   

ThinkPHP3.2URL重寫隱藏應用的入口檔案index.php

可以通過URL重寫隱藏應用的入口檔案index.php,下面是相關伺服器的配置參考: [ Apache ] httpd.conf配置檔案中載入了mod_rewrite.so模組AllowOverride None 將None改為 All把下面的內容儲存為.htacces

thinkPHP5隱藏入口檔案index.php後 讀取不到資源問題

這個問題弄了一下午 <link rel="stylesheet" href="../../../public/static/css/information_content.css" /> 在隱藏入口檔案後,這種方式會不成功 ,所以我們需要在配置檔案config.

ThinkPHP5 Nginx下的配置——支援pathinfo訪問和隱藏入口檔案index.php的rewrite規則

最近賦閒在家,看到TP都更新到5.0.6了,於是弄過來寫了個小專案熟悉了下,發現改動確實蠻大的。首先就是支援Composer了。(強烈建議使用Composer安裝,因為TP5的一些驗證碼之類的擴充套件包必須要用到Composer來安裝。)檔案命名規範的改變:控制器類檔名“Us

Apache伺服器下無法隱藏tp5的入口檔案index.php

找到Wampserver伺服器檔案httpd.conf 去掉‘#LoadModule rewrite_module modules/mod_rewrite.so’前面的‘#’ 。 查詢AllowOverride 。 <Directory "E

tp5隱藏入口檔案index.php

為什麼要隱藏入口檔案 使頁面url美觀,方便搜尋引擎收錄 具體實現 在index.php同級目錄下新建.htaccess(預設自帶) 新增如下內容 <IfModule

thinkphp5重寫隱藏應用的入口檔案index.php Apache IIS Nginx

可以通過URL重寫隱藏應用的入口檔案index.php,下面是相關伺服器的配置參考:[ Apache ]1.      httpd.conf配置檔案中載入了mod_rewrite.so模組2.      AllowOverride None 將None改為 All3.