首頁 >後端開發 >php教程 >Yii運作機制及路由詳解

Yii運作機制及路由詳解

*文
*文原創
2017-12-29 19:05:403148瀏覽

本文主要介紹了PHP的Yii框架的運作機制及其路由功能,Yii是一個基於元件的重量級的PHP框架,適合用來開發大型網站。需要的朋友可以參考下。希望對大家有幫助。

運行機制概述
每一次 Yii 應用程式開始處理 HTTP 請求時,它都會進行一個近似的流程。

  • 使用者提交指向 入口腳本 web/index.php 的請求。

  • 入口腳本會載入 設定陣列 並建立一個 應用程式 實例用於處理該請求。

  • 應用程式會透過 request(請求) 應用元件解析被請求的 路由。

  • 應用程式建立一個 controller(控制器) 實例具體處理請求。

  • 控制器會建立一個 action(動作) 實例並為該動作執行相關的 Filters(存取過濾器)。

  • 如果任何一個篩選器驗證失敗,則該動作會被取消。

  • 如果全部的濾鏡都通過,該動作就會被執行。

  • 動作會載入一個資料模型,一般是從資料庫載入。

  • 動作會渲染一個 View(視圖),並提供所需的資料模型。

  • 渲染所得到的結果會回傳給 response(回應) 應用程式元件。

  • 回應元件會把渲染結果傳回給使用者的瀏覽器。

下面的示意圖顯示了應用程式是如何處理一個請求的。

2016317145658183.png (1144×876)

啟動引導(Bootstrapping)
#啟動引導是指:在應用開始解析並處理新接受請求之前,一個預先準備環境的過程。啟動引導會在兩個地方具體進行:入口腳本(Entry Script) 和 應用主體(application)。

在入口腳本裡,需註冊各個類別庫的類別檔案自動載入器(Class Autoloader,簡稱自動載入器)。這主要包括透過其 autoload.php 檔案載入的 Composer 自動載入器,以及透過 Yii 類別載入的 Yii 自動載入器。之後,入口腳本會載入套用的 配置(configuration) 並建立一個 應用主體 的實例。

在應用主體的建構函式中,會執行下列開機工作:

  • #呼叫yii\base\Application::preInit()(預先初始化)方法,配置一些高優先權的應用屬性,例如yii\base\Application::basePath 屬性。

  • 註冊yii\base\Application::errorHandler。

  • 透過給定的應用程式配置初始化應用的各屬性。

  • 透過呼叫 yii\base\Application::init()(初始化)方法,它會順次呼叫 yii\base\Application::bootstrap() 從而執行引導元件。

  • 載入擴充功能清單檔案(extension manifest file) vendor/yiisoft/extensions.php。

  • 建立並執行各個擴充宣告的 引導元件(bootstrap components)。

  • 建立並執行各個 應用程式元件 以及在應用程式的 Bootstrap 屬性中宣告的各個 模組(modules)元件(如果有)。

因為引導工作必須在處理每一次請求之前都進行一遍,因此讓過程盡可能輕量化就異常重要,請盡可能地優化這一步驟。

請盡量不要註冊太多引導元件。只有他需要在 HTTP 請求處理的全部生命週期中都作用時才需要使用它。舉一個用到它的範例:一個模組需要註冊額外的 URL 解析規則,就應該把它列在應用的 bootstrap 屬性之中,這樣該 URL 解析規則才能在解析請求之前生效。 (譯註:換言之,為了性能需要,除了URL 解析等少量操作之外,絕大多數組件都應該按需加載,而不是都放在引導過程中。)

在生產環境中,可以開啟字節碼緩存,例如APC,來進一步最小化載入和解析PHP 檔案所需的時間。

一些大型應用程式都包含有非常複雜的應用程式配置,它們會被分割到許多較小的設定檔中。此時,可以考慮將整個配置數組快取起來,並在入口腳本建立應用實例之前直接從快取中載入。


yii的入口檔案
這裡使用了一個第三方的設定管理外掛:marcovwout,來管理Yii的配置,細節我就不說了。剩下的就是一些基本的全域變數設定了。往Yii::createWebApplication裡面傳入配置的數組,然後呼叫run方法,一個web應用程式是不是就這麼跑起來了,是的,抽像到最高層就是這樣:我往一個容器裡面傳入對應的配置,然後這個應用可以基於該配置正常運作起來。
說YiiBase中的兩個比較重要的方法 (import,autoload)

2016317145740223.png (561×219)

這裡使用了一個第三方的設定管理外掛:marcovwout,來管理Yii的配置,細節我就不說了。剩下的就是一些基本的全域變數設定了。往Yii::createWebApplication裡面傳入配置的數組,然後呼叫run方法,一個web應用程式是不是就這麼跑起來了,是的,抽像到最高層就是這樣:我往一個容器裡面傳入對應的配置,然後這個應用可以基於該配置正常運作起來。

路由
當入口腳本在呼叫yii\web\Application::run() 方法時,它進行的第一個操作就是解析輸入的請求,然後實例化對應的控制器操作處理這個請求。這個過程就被稱為引導路由(routing)。 (譯註:中文裡既是動詞也是名詞)

解析路由

#路由引導的第一步,是把傳入請求解析為一個路由。如我們在 控制器(Controllers) 章節中所描述的那樣,路由是一個用於定位控制器操作的位址。這個過程透過 request 應用程式元件的 yii\web\Request::resolve() 方法實現,該方法會呼叫 URL 管理員 進行實質上的請求解析工作。

預設情況下,傳入請求會包含一個名為 r 的 GET 參數,它的值即被視為路由。但是如果啟用 yii\web\UrlManager::enablePrettyUrl,那麼在確定請求的路由時,就會進行更多處理。具體的細節請參考 URL 的解析與產生 章節。

假使某路由最終實在無法被確定,那麼 request 元件會拋出 yii\web\NotFoundHttpException 異常(譯:大名鼎鼎的 404)。

預設路由

如果傳入請求並沒有提供一個具體的路由,(一般這種情況多為於對首頁的請求)此時就會啟用由yii\web\Application::defaultRoute 屬性所指定的預設路由。此屬性的預設值為 site/index,它指向 site 控制器的 index 操作。你可以像這樣在應用程式設定中調整該屬性的值:

return [
  // ...
  'defaultRoute' => 'main/index',
];

catchAll 路由(全攔截路由)

有時候,你會想要將你的Web 應用程式暫時調整到維護模式,所有的請求下都會顯示相同的資訊頁。當然,要實現這一點有很多種方法。這裡面最簡單快速的方法就是在應用程式設定中設定下yii\web\Application::catchAll 屬性:

return [
  // ...
  'catchAll' => ['site/offline'],
];

catchAll 屬性需要傳入一個陣列做參數,該陣列的第一個元素為路由,剩下的元素會(以名值對的形式)指定綁定於此運算的各個參數。

當設定了 catchAll 屬性時,它會取代掉所有從輸入的請求中解析出來的路由。如果是上文的這種設置,用於處理所有傳入請求的操作都會是相同的 site/offline。

建立操作

一旦請求路由被確定了,緊接著的步驟就是建立一個「操作(action)」對象,用以回應該路由。

路由可以用裡面的斜線分割成多個組成片段,舉個栗子,site/index 可以分解為 site 和 index 兩部分。每個片段都是指向某一模組(Module)、控制器(Controller)或操作(action)的 ID。

從路由的首個片段開始,應用程式會經過以下流程依序建立模組(如果有),控制器,以及操作:

  • 設定應用程式主體為目前模組。

  • 檢查目前模組的 yii\base\Module::controllerMap 是否包含目前 ID。如果是,會根據該表中的配置建立一個控制器對象,然後跳到步驟五執行該路由的後續片段。

  • 檢查該 ID 是否指向目前模組中 yii\base\Module::modules 屬性裡的模組清單中的一個模組。如果是,會根據該模組表中的配置建立一個模組對象,然後會以新建立的模組為環境,跳回步驟二解析下一段路由。

  • 將該 ID 視為控制器 ID,並建立控制器物件。用下個步驟解析路由裡剩下的片段。

  • 控制器會在他的 yii\base\Controller::actions()裡搜尋目前 ID。如果找到,它會根據該映射表中的配置建立一個操作物件;反之,控制器則會嘗試建立一個與該 ID 相對應,由某個 action 方法所定義的行內操作(inline action)。

在上面的步驟裡,如果有任何錯誤發生,都會拋出 yii\web\NotFoundHttpException,指出路由引導的過程失敗了。

相關推薦:

YII關聯查詢詳解

##Yii2中的程式碼自動載入機制#

載入Yii自帶的驗證碼功能的方法

以上是Yii運作機制及路由詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn