CI框架入門筆記

當前(2019-03-22)CodeIgniter 框架的最新版本是 3.1.5,於2017年6月發佈,距今快兩年了也沒有更新,這與 Laravel 的更新速度相比差距太大了。由於確實,它是一個很古老的框架了(第一個版本在2006年發佈),當初的設計原則,開發環境與如今都已經大爲不一樣。它有本身的設計原則,有相配套的一大堆工具、庫,使用這些現有的工具就已經能很好地知足平常開發所需。php

雖然已是2019年了,可是公司用的框架是CI框架,因此我也應當快速適應CI框架的開發模式。本文就針對CI框架開發中的一些重點問題進行梳理和記錄。CI框架的官網文檔( http://codeigniter.org.cn/user_guide/index.html )很完善,可是我以爲仍然有必要整理出本身的一套實用規則。html

就一個常規PHP框架來講,我認爲應當包含這幾個部分:git

  • (1)index.php 或全局 App 對象,一個提供統一入口,一個提供容器資源管理
  • (2)路由控制
  • (3)請求和響應對象的封裝,輸入數據過濾和驗證,輸出數據的驗證和轉義,各類輸入輸出方法
  • (4)MVC 分層,控制器,模型和視圖層,以及 Service 層
  • (5)數據庫操做:數據庫驅動、查詢構造器、通用的查詢方法
  • (6)文件存儲、緩存管理
  • (7)Session, Cookie管理
  • (8)安全性、配置、國際化、自動加載、第三方擴展機制
  • (9)常見的工具類(其實應當經過擴展提供)
  • (10)模板語言(這個不是必要的,由於PHP自己就能輸出)

入門

瞭解框架

咱們下載好CI框架解壓以後的初始目錄是下面這樣的:數據庫

application/
    controller/
        cache/
        config/
        controllers/
        core/
        helpers/
        hooks/
        language/
        libraries/
        logs/
        models/
        third_party/
        views/
        .htaccess
        index.html
system/
    core/
    database/
    fonts/
    helpers/
    language/
    libraries/
    index.html
.gitignore
composer.json
index.php

其中,我注意到,每一個目錄下面都有一個index.html文件,其內容也都是同樣的:403 Forbidden。這是爲了防止意外訪問嗎?json

application/ 就是是項目目錄,就是咱們實際的項目代碼存放處,下面分了不少子目錄,看名字就知道會放哪一種功能的代碼,這些子目錄目前除了包含一個 403 index.html 文件,沒有別的內容。system/ 就是框架目錄,下面就是框架代碼。數組

根目錄的 index.php 是整個項目的惟一入口點。index.php 主要的功能是定義了一些系統目錄,包括項目目錄、視圖目錄、框架目錄,在最後調用了框架目錄下的 core/CodeIgniter.php,這個文件是CI框架的入口點和結束點,即包含了CI框架的全部生命週期。它的執行過程以下:緩存

* 定義全局常量,加載全局函數,環境檢測,PHP版本判斷
* 註冊錯誤處理函數,自動加載函數(Composer判斷)
* 加載一系列類:
    * Hooks,鉤子函數類
    * Config,配置類
    * UTF-8,
    * URI,(CI_URI)
    * Router,路由類
    * Output,輸出類
    * Security,安全類
    * Input,輸入類
    * Lang,多語言類
* 加載控制器類
    * 判斷控制器類、方法是否存在,不存在則404
    * 調用控制器前置鉤子函數
    * 實例化控制器
    * 調用控制器後置鉤子函數
    * 調用控制器方法(業務邏輯)
    * 輸出響應
* 調用系統後置鉤子函數

在實例化控制器這一部分中,注意到它定義了一個靜態實例,代碼以下安全

# core/CodeIgniter.php
# 此處定義了一個全局函數 get_instance(),返回一個靜態對象。
function &get_instance()
{
    return CI_Controller::get_instance();
}
// ...

$CI = new $class();


# core/Controller.php
class CI_Controller {
    public function __construct()
    {
        self::$instance =& $this;
        // ...
    }

    public static function &get_instance()
    {
        return self::$instance;
    }
}

在以後的任意位置的代碼中,只要經過 get_instance() 方法就能獲取惟一的 Controller 對象,它其實就是CI框架中的「容器」。app

調用控制器方法(即業務邏輯)經過這段代碼調用執行:composer

call_user_func_array(array(&$CI, $method), $params);

業務邏輯

在調用上述代碼以後,就進入到 application/ 目錄下咱們的實際的業務功能代碼。上面的 &$CI 就是 $class 名對象,即根據URL參數解析對應到 application/controllers/ 目錄下的實際控制器類文件名。具體的映射方法能夠看文檔( https://codeigniter.org.cn/user_guide/general/controllers.html

好比,有一個 URI 是這樣的:/welcome,會解析爲 application/controller/Welcome.php 文件,它應該是一個繼承自 CI_Controller 的類。/welcome 至關於 /welcome/index,URI 的第一個部分是控制器,第二個部分是控制器的方法,因此這個 URI 會調用 Welcome 類的 index 方法。URI 中只有第一個部分時,那第二個部分默認是 index。在控制器方法中咱們編寫實際的業務功能代碼。示例以下:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Welcome extends CI_Controller {

    public function index()
    {
        $this->load->view('welcome_message');
    }
}

加載功能模塊(類庫)

CI框架默認提供了模型、視圖、輔助函數、日誌、配置、緩存等功能。這些功能模塊默認是不加載的,須要在控制器中進行手動按需加載。另外,libraries 目錄中的類庫,也是同上的加載機制,只不過這裏面的類庫是開發人員本身寫的功能模塊。下面詳細描述每種模塊的加載方式。

model

首先,咱們看到上節中的 $this->load,這就是CI框架中的加載類(CI_Loader),咱們全部須要的類庫、模塊均可以經過它來加載。這個加載類其實是「容器」的一個對象屬性,從下面 model 的源碼能夠看到,實際上全部容器的「對象屬性」均可以直接經過模型獲取:

class CI_Model {
    public function __get($key)
    {
        return get_instance()->$key;
    }
}

在業務功能開發中,使用最頻繁的就是模型了。CI框架提供的模型類是 core/Model.phpCI_Model 類,它其實就是一個很簡單的類,沒有提供任何內容,若是你須要使用模型,那就應該在 application/models 下面新建一個繼承自 CI_Model 的類,而後在使用模型的地方先使用 $this->load->model() 來加載它,加載了以後,就能直接經過 $this->{模型名} 訪問該模型對象:

$this->load->model('User_model');
 $result = $this->User_model->get_one($id);

model() 默認到 application/model/ 目錄下尋找 user_model.php 這個文件名,而後加載 User_model 類,實例化之,並賦值做爲「容器」的對象屬性,屬性名就是模型名。model() 方法部分源碼:

public function model($model, $name = '', $db_conn = FALSE)
{
    // ...
    $model = new $model();
    $CI->$name = $model;
}

model() 方法的第二個參數能夠指定屬性名,示例代碼以下:

$this->load->model('User_model', 'USER');
$result = $this->USER->get_one($id);

CI框架並無規定模型類中應當放什麼,這取決於你。一般咱們會寫一個 Base_Model 類,用來提供各類查詢方法,而後在具體的模型類中實現具體模型對應的業務方法。在控制器中直接調用模型類的業務方法獲取數據。在CI框架中咱們使用模型類的理由就是封裝邏輯,否則全部的邏輯都寫在控制器中(我看到項目中如今有一部分老代碼就是這樣作的!)。CI也沒有提供進一步Service層,這由你本身決定。

database

通常在 Base_Model 類中,咱們會加載一下默認的數據庫,封裝若干查詢方法:

class Base_Model 
{
    function __construct()
    {
        // ...
        $this->load->database();
    }

    function save() {}
    function get_one() {}
    function get_all() {}
    function update() {}
    function delete() {}
    function query() {}
    ...
}

調用了 database() 以後,會實際化一個 CI_DB 對象,並賦值爲控制器的 $db 屬性,database() 部分源碼以下:

public function database($params = '', $return = FALSE, $query_builder = NULL)
{
    // ...
    if ($return === TRUE)
    {
        return DB($params, $query_builder);
    }
    // ...
    $CI->db =& DB($params, $query_builder);
}

能夠看到,當第二個參數爲 TRUE 時,直接返回 DB 對象,並不會設置爲控制器的屬性。這一點在具體的模型類中會有用,好比咱們會在具體的模型類中加載不一樣的數據庫類:

class Article_model extends Base_Model
{   
    public function __construct()
    {
        $this->db = $this->load->database('myDb2', TRUE);
    }
}

這裏獲取 myDb2 數據庫對象,避免了污染全局的 $CI->db 對象。

最複雜的部分其實已經介紹完了,下面是一些經常使用的類庫介紹

helper

在使用自定義的輔助函數以前,須要加載一下,語法同上。只不過它會去 application/helpers 目錄下去尋找相應文件。

$this->load->helper('dt');

libraries

application/libraries 目錄下的類,加載語法同上,使用其實沒什麼問題,值得注意的是如何寫一個本身的類庫。

$this->load->library('t');

config

配置文件也須要加載,而後 item 方法直接訪問配置文件中的值,自定義的配置須要設置爲 $config 數組的屬性的形式。

# application/config/d.php
$config['ddd'] = '';

# Controller
$this->load->config('d');
$data = $this->config->item('ddd')

view

因爲如今CI項目只是做爲API,因此並沒有視圖,但爲了介紹,下面提供了一個示例:

# application/views/welcome.php

# Controller
$this->load->view('welcome', $data);

這個視圖文件就是一個普通的PHP文件,能夠直接輸出。

driver

驅動其實也是類庫的一種。

總結

就我入手這個CI項目的一個月經驗來看,平常業務開發就是這些東西,後面也不過是在這個框架基礎上不斷深刻和完善。因此這篇文章做爲入門總結應該算是足夠了。

PS - 我的博客連接 CI框架入門筆記

相關文章
相關標籤/搜索