Yii2 框架總體結構

Yii2框架是一個很是龐大可是並不臃腫的 php 框架。使用 Yii2 框架,能夠極大的提高開發效率。 秉持着要知其然也要知其因此然的思想,花了一週的時間,看了 linuor 的 《深刻理解Yii2.0》 根據個人理解梳理了一下 Yii2 框架的總體結構。此後簡稱框架。php

Yii 框架基礎

此框架的三個基礎概念:程序員

  • 屬性
  • 事件
  • 行爲

畢竟三生萬物。web

屬性

一看到這個詞可能很迷惑,那麼什麼是屬性呢。 好比說,你如今正在玩一款角色扮演的遊戲,角色雙手分別有一把 十方大劍 ,一個 十方盾牌。 那麼從面向對象的角度而言,你的角色類須要有 左手武器右手武器 兩個成員變量。 而且角色類能夠從 左手武器右手武器 中得到 力量屬性。數據庫

這麼一說屬性這一律念,就很容易理解了。設計模式

事件

仍是以角色扮演遊戲爲例(這裏要對不起不玩遊戲的朋友了,原諒我匱乏的想象力,或者你有好的比喻也能夠跟我說),遊戲裏面都有任務系統,而任務會分爲主線任務和支線任務,在作主線任務是一般會觸發一系列的支線任務。這些支線任務的觸發就能夠認爲是一系列的事件。網絡

行爲

框架的行爲也可使用角色扮演遊戲來舉例,你在 無盡荒原 撿到了一本魔法書,學會了禁咒魔法,召喚神龍。 因而你把程序一改,給你的類加一個召喚魔法的方法,這是不可能的。咱們必須讓你的類擁有一個動態添加方法的功能,因而全部拿到魔法書的人或者限定職業的人,都能學會這個禁咒,這就是 行爲 的做用,動態給類增長方法。架構

以上,有了這三個 框架 實現的武器,咱們才能更快速和靈活的搭建上層的程序。框架

設計模式

依賴注入

框架採用瞭如今世面上面最多見的一種模式, MVC 模式,具體細節再也不闡述,如今網上關於 MVC 的介紹能夠說是爛大街了。 MVC 只是一種大框架上的設計模式,其核心思想是分層,最終目的是解耦。框架在 MVC 的基礎上,應用了不少經典的設計模式以及後來發展的設計模式。yii

其中最重要的就是:this

  • 依賴注入
  • 服務定位器。

那麼什麼是依賴注入呢 先來一段沒有依賴注入的代碼:

<?php
// 這段代碼將 db1 中的t1表的數據備份到 db2 庫的 t2 中。
// 所使用的變量都在邏輯過程當中申請。
class Archive {
    public function doArchive() {
        $dataDB = new DB1();
        
        $data = $dataDB->query("select * from t1");

        $backDB = new DB2();

        foreach ($data as $key => $value) {
            $backDB->query("insert into t2 values ". implode(',', $value));
        }

        die("備份完成");
    }
}

那麼若是再來一個需求,讓你把 db3 的數據備份到 db4 中,邏輯相同,那麼你該怎麼辦呢? 有道友就說了,那還不簡單, copy & paste,搞定。 因而,你多了一個方法或者一個類。 一直到你的方法和類增長到10個以上時,你都不會有什麼感受。 直到產品說如今需求變了,讓你把全部的備份庫都改爲 db3,那麼,你就要把手頭的工做都停下來,而後將代碼中的備份庫全改爲 db3。

並且,若是你使用的是靜態語言,那麼,你就要把代碼再從新編譯一遍。關於靜態語言的編譯時長:爲何c編譯須要這麼長時間

那麼就有了下面這種:

class ArchiveNew {
    private $originDb;
    private $backDb;

    public function doArchive() {
        $dataDB = new $this->originDb();
        
        $data = $dataDB->query("select * from t1");

        $backDB = new $this->backDb();

        foreach ($data as $key => $value) {
            $backDB->query("insert into t2 values ". implode(',', $value));
        }

        die("備份完成");
    }

    /**
     * @param mixed $originDb
     */
    public function setOriginDb($originDb)
    {
        $this->originDb = $originDb;
    }

    /**
     * @param mixed $backDb
     */
    public function setBackDb($backDb)
    {
        $this->backDb = $backDb;
    }
}

這個方法,把全部的須要用到的數據庫都放到了外面來進行管理,那麼咱們稱這幾個數據庫爲依賴,稱在外部設置數據庫的行爲爲依賴注入。 這只是一種很原始的使用方式,你能夠繼續延伸,將外部依賴放到統一的地方去管理,那麼就有了注入容器(di Container)

服務定位器

服務定位器像是一個註冊中心,向服務定位器中註冊一個 a 服務,可使用 a 這個名字從服務定位器中取出這個服務。

$locator = new ServiceLocator;
$locator->set('a');
$locator->get('a');

服務定位器是基於依賴注入的,在獲取服務時,其實會在容器中先註冊一個服務。

請求與響應

這一節其實主要講的就是請求。 請求的內容會比較多,還涉及到網絡協議等知識,這裏再也不展開。 列舉一下重要的幾點:

  1. 路由美化 (將原始的路由修改爲比較美觀的地址,見導圖 請求部分)
  2. url 解析(將美化過的路由解析成原始請求)
  3. 請求管理 (包括請求頭部,請求體,解析器等等)

數據庫

雖然這張圖有些搞笑,可是無疑說明了 數據庫(MySQL)對於 PHP 的重要性。

類型轉換

框架爲了兼容各類數據庫,對數據類型作了多層封裝,而且作了一系列的轉換規則:

事務

框架支持事務嵌套,可是嵌套的事務必須成對出現(注意!!!)。 看到事務這一節的時候,正巧同事出了一個 bug ,在腳本的循環中,出錯以後沒有 commit 或者 rollback ,致使,接下來的生成的事務都成了這個事務的子事務。而框架的嵌套事務,其實是使用代碼模擬的,若是父事務沒有提交,那麼子事務永遠不會提交。

事件

const EVENT_INIT = 'init';                      // 初始化對象時觸發
const EVENT_AFTER_FIND = 'afterFind';           // 執行查詢結束時觸發
const EVENT_BEFORE_INSERT = 'beforeInsert';     // 插入結束時觸發
const EVENT_AFTER_INSERT = 'afterInsert';       // 插入以前觸發
const EVENT_BEFORE_UPDATE = 'beforeUpdate';     // 更新記錄前觸發
const EVENT_AFTER_UPDATE = 'afterUpdate';       // 更新記錄後觸發
const EVENT_BEFORE_DELETE = 'beforeDelete';     // 刪除記錄前觸發
const EVENT_AFTER_DELETE = 'afterDelete';       // 刪除記錄後觸發

這些事件和其餘事件沒有什麼分別,都是在特定的時候會執行,就不一一闡述了。

樂觀鎖和悲觀鎖

框架自帶了樂觀鎖的實現,若是有相似需求,能夠在重載yii\db\ActiveRecord::optimisticLock() 方法,返回數據庫中的版本號字段便可。在更新與刪除時,框架會作相應的操做,來保證,更新的數據是本身拿到的數據,而不是被別人給修改過了。 由於悲觀鎖不適用於 web 應用,因此框架並無實現悲觀鎖。

總結

Yii2 框架的總體架構要比 1 版本提高了一個逼格。而且得益於 namespace 特性,框架的目錄結構清晰了不少。 對於不想了解框架底層實現的程序員,能夠僅僅瞭解基本使用,就能夠上手寫業務代碼,而不會影響你的開發效率。 只有當你碰見一個很蛋疼的框架內部報錯或者 bug 的時候,你纔會想到,我去,這怎麼這麼蛋疼,怎麼框架還會有 bug ,可是不少時候是環境、配置或者特定的代碼致使的。若是不瞭解框架的內部邏輯,這個報錯或者 bug 會耽誤你很長時間。

相關文章
相關標籤/搜索