yii2深入理解之內核解析


一、前言

 

首先,yii2最為為數不多的PHP主流開源框架,受歡迎程度不亞於laravel和TP。個人認為,研究這些框架底層代碼是非常有助於自身代碼編程思想的提升和代碼簡化程度和質量的提升的。

那么,話不多說,下面開始說一下自己對yii2底層框架架構的理解。

二、客戶端請求處理

 

yii2對客戶請求處理,提供了url美化類urlManager,這點在最初通過composer加載,並初始化框架時,已經在config目錄下的main文件里生成了, 只不過時注釋過的,如果需要url美化則取消掉注釋即可。其實,yii2對apache的支持是非常的好的。

說到這了,那么我們就說一下,后端最流行的兩個服務器,apache和nginx的區別。

a、nginx性能比apache要好很多,相比apache,但bug就會相對多。

b、nginx相比apache輕量級了不少,配置也相對簡單,而且,對高並發的請求事件處理,可以是異步非阻塞的處理請求,能消耗低。

c、apache相比nginx,它的重寫能力要比nginx強很多,而且,功能模塊比nginx多很多,其性能比nginx穩定,bug較少。

所以說,yii2的url美化組件urlManager對apache服務器有很好的支持。

框架和項目配置,我們可以直接在common文件下的config文件下的main-local文件里配置,數據庫的連接以及數據表的前綴等。web文件夾下的.htaccess文件內容如下:

 1  Header always set Access-Control-Allow-Origin "*"
 2  Header always set Access-Control-Allow-Headers: "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
 3  RewriteEngine ON
 4  RewriteCond %{REQUEST_FILENAME} !-f
 5  RewriteCond $1 !^(index\.php|robots\.txt|favicon\.ico|Sitemap\.xml|pma)
 6  RewriteRule ^(.*)$ index.php/$1 [L]
 7  php_value upload_max_filesize "50M"
 8 php_value post_max_size "50M"
 9 php_value max_execution_time "40000"
10 php_value memory_limit "128M"

代碼解析一下:

RewriteEngine On

指令含義:命令apache或nginx重寫功能開啟。

RewriteCond %{REQUEST_FILENAME} !-f

指令含義:URI匹配內容為非文件。

RewriteCond $1 !^(index\.php|robots\.txt|favicon\.ico|Sitemap\.xml|pma)

指令含義:URI匹配內容非文件,除了這幾個文件。注:這里用到了正則的反引用。

RewriteRule ^(.*)$ index.php/$1 [L]

指令含義:URL匹配規則,index.php/site/login

下面來看一下web目錄下的文件都有哪些:

a. assets yii2底層必備靜態文件夾,這里放了一些,yii2靜態模板組件的必須引入的靜態文件。如:jQuery,bootstrap等。注:此文件夾不可刪除;

assets文件夾下面的文件,在你第一次訪問項目時,會自動生成靜態文件,這里用到了yii2的另外一個服務和組件assetManager,在它的里面有一個方法,publish(),其具體用法如下:

1 <?php
2 
3 list(, $dir) = Yii::$app->getAssetManager()->publish('@backend/rbac/plugins');
4 $svg = $dir . '/image/loading.svg';

此方法需要傳入一個alias路由,這alias路由其實在common文件下的config文件夾下的bootstrap.php已經配置。代碼如下:

1 <?php
2 Yii::setAlias('@common', dirname(__DIR__));
3 Yii::setAlias('@frontend', dirname(dirname(__DIR__)) . '/frontend');
4 Yii::setAlias('@backend', dirname(dirname(__DIR__)) . '/backend');
5 Yii::setAlias('@console', dirname(dirname(__DIR__)) . '/console');
6 Yii::setAlias('@wechat', dirname(dirname(__DIR__)) . '/wechat');
7 Yii::setAlias('@api', dirname(dirname(__DIR__)) . '/api');

當傳入alias路由,此方法會解析出文件絕對路由,並在assets文件夾下生成對應的文件夾和其文件。這個方法用到了crc32()多項冗余算法,通過文件名和文件修改時間,生成帶有符號的crc32值,並通過sprinf()轉換為16進制字符作為文件名。

b.css文件這里面寫入了項目需要引入的前端靜態文件,比如:css,js,svg,圖片等;

三、index.php腳本文件運行機制


項目腳本文件,最后一行簡潔的代碼,包含了yii2架構所有運行的機制。

<?php
(new yii\web\Application($config))->run();


這里有幾個類:

1.yii\web\Application

2.yii\base\Application

3.yii\base\Module

4.yii\di\ServiceLocator

5.yii\base\component

6.yii\base\BaseObject

首先,new yii\web\Application類,這里的構造函數在yii\base\Application下:

1 public function __construct($config = [])
2 {
3 Yii::$app = $this;
4 static::setInstance($this);
5 
6 $this->state = self::STATE_BEGIN;
7 
8 $this->preInit($config);
9 
10 $this->registerErrorHandler($config);
11 
12 Component::__construct($config);
13 }


這里它做了什么?

1.單例yii\web\Application應用核心類。

2.注冊yii\web\Application模塊到注冊樹。

3.指定web應用運行狀態:初始化

4.初始化配置,拉入common和backend目錄下config目錄下bootstrap.php文件配置。

5.注冊錯誤處理程序。

6.加載核心組件、核心配置、以及自定義行為組件等。(注:這些都是common和backend文件下config文件下main.php里面的內容)

接下來運行run方法:

1 public function run()
2 {
3 try {
4 $this->state = self::STATE_BEFORE_REQUEST;
5 $this->trigger(self::EVENT_BEFORE_REQUEST);
6 
7 $this->state = self::STATE_HANDLING_REQUEST;
8 $response = $this->handleRequest($this->getRequest());
9 
10 $this->state = self::STATE_AFTER_REQUEST;
11 $this->trigger(self::EVENT_AFTER_REQUEST);
12 
13 $this->state = self::STATE_SENDING_RESPONSE;
14 $response->send();
15 
16 $this->state = self::STATE_END;
17 
18 return $response->exitStatus;
19 } catch (ExitException $e) {
20 $this->end($e->statusCode, isset($response) ? $response : null);
21 return $e->statusCode;
22 }
23 }

這個方法里包含了從初始化beforeRequest事件,到afterRequest的所有程序,可謂是核心方法。

那么咱們來看一下,都有些什么?

首先,執行beforeRequest綁定的事件,指定web應用運行狀態。

后者,處理請求url和參數。

再者,解析路由,實例化controller類、action類。

然后,執行beforeAction事件和處理action程序、afterAction事件。

最后,執行afterRequest事件,實例response指定data,響應客戶端。

好了,由於時間關系,這次就解析這么多。如有建議和不同意見,請關注博客,敬請留言。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM