4 追蹤者

應用程式

應用程式是管理 Yii 應用程式系統整體結構和生命週期的物件。每個 Yii 應用程式系統都包含一個應用程式物件,該物件在進入腳本中建立,並且可以透過 \Yii::$app 表達式全域存取。

資訊:根據上下文,當我們說「應用程式」時,它可以指應用程式物件或應用程式系統。

應用程式有兩種型別:Web 應用程式命令列應用程式。顧名思義,前者主要處理 Web 請求,而後者處理命令列指令請求。

應用程式配置

進入腳本建立應用程式時,它將載入配置並將其應用於應用程式,如下所示

require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';

// load application configuration
$config = require __DIR__ . '/../config/web.php';

// instantiate and configure the application
(new yii\web\Application($config))->run();

像一般的配置一樣,應用程式配置指定如何初始化應用程式物件的屬性。由於應用程式配置通常非常複雜,因此它們通常保存在配置檔案中,例如上面範例中的 web.php 檔案。

應用程式屬性

有許多重要的應用程式屬性,您應該在應用程式配置中配置它們。這些屬性通常描述應用程式運行的環境。例如,應用程式需要知道如何載入控制器、在哪裡儲存臨時檔案等等。在下面,我們將總結這些屬性。

必要屬性

在任何應用程式中,您至少應該配置兩個屬性:idbasePath

id

id 屬性指定一個唯一的 ID,用於區分應用程式與其他應用程式。它主要以程式方式使用。雖然不是必需的,但為了獲得最佳的互操作性,建議您在指定應用程式 ID 時僅使用字母數字字元。

basePath

basePath 屬性指定應用程式的根目錄。它是包含應用程式系統所有受保護原始碼的目錄。在此目錄下,您通常會看到子目錄,例如 modelsviewscontrollers,它們包含對應於 MVC 模式的原始碼。

您可以使用目錄路徑或路徑別名來配置 basePath 屬性。在這兩種形式中,相應的目錄都必須存在,否則將拋出例外。路徑將透過呼叫 `realpath()` 函數進行正規化。

basePath 屬性通常用於衍生其他重要路徑(例如,runtime path)。因此,預先定義了一個名為 `@app` 的路徑別名來表示此路徑。然後可以使用此別名形成衍生路徑(例如,`@app/runtime` 指的是 runtime 目錄)。

重要屬性

本小節中描述的屬性通常需要配置,因為它們在不同的應用程式中有所不同。

aliases

此屬性允許您以陣列的形式定義一組別名。陣列鍵是別名名稱,陣列值是對應的路徑定義。例如

[
    'aliases' => [
        '@name1' => 'path/to/path1',
        '@name2' => 'path/to/path2',
    ],
]

提供此屬性是為了讓您可以根據應用程式配置定義別名,而不是透過呼叫 Yii::setAlias() 方法。

bootstrap

這是一個非常有用的屬性。它允許您指定一個組件陣列,這些組件應在應用程式啟動引導過程中執行。例如,如果您想要讓模組自訂 URL 規則,您可以將其 ID 列為此屬性中的一個元素。

此屬性中列出的每個組件都可以以下列格式之一指定

  • 透過 components 指定的應用程式組件 ID,
  • 透過 modules 指定的模組 ID,
  • 類別名稱,
  • 配置陣列,
  • 建立並傳回組件的匿名函數。

例如

[
    'bootstrap' => [
        // an application component ID or module ID
        'demo',

        // a class name
        'app\components\Profiler',

        // a configuration array
        [
            'class' => 'app\components\Profiler',
            'level' => 3,
        ],

        // an anonymous function
        function () {
            return new app\components\Profiler();
        }
    ],
]

資訊:如果模組 ID 與應用程式組件 ID 相同,則在啟動引導過程中將使用應用程式組件。如果您想改用模組,可以使用類似以下的匿名函數來指定它

[
    function () {
        return Yii::$app->getModule('user');
    },
]

在啟動引導過程中,每個組件都將被實例化。如果組件類別實作了 yii\base\BootstrapInterface,則也會呼叫其 bootstrap() 方法。

另一個實際範例是在 Basic Project Template 的應用程式配置中,當應用程式在開發環境中執行時,`debug` 和 `gii` 模組被配置為啟動引導組件

if (YII_ENV_DEV) {
    // configuration adjustments for 'dev' environment
    $config['bootstrap'][] = 'debug';
    $config['modules']['debug'] = 'yii\debug\Module';

    $config['bootstrap'][] = 'gii';
    $config['modules']['gii'] = 'yii\gii\Module';
}

注意:在 `bootstrap` 中放置過多組件會降低應用程式的效能,因為對於每個請求,都需要執行相同的組件集。因此,請明智地使用啟動引導組件。

catchAll

此屬性僅由 Web 應用程式 支援。它指定一個控制器動作,該動作應處理所有使用者請求。這主要用於應用程式處於維護模式並且需要透過單一動作處理所有傳入請求時。

配置是一個陣列,其第一個元素指定動作的路由。陣列的其餘元素(鍵值對)指定要繫結到動作的參數。例如

[
    'catchAll' => [
        'offline/notice',
        'param1' => 'value1',
        'param2' => 'value2',
    ],
]

資訊:當啟用此屬性時,開發環境中的除錯面板將無法運作。

components

這是最重要的屬性。它允許您註冊一個名為應用程式組件的具名組件清單,您可以在其他地方使用它們。例如

[
    'components' => [
        'cache' => [
            'class' => 'yii\caching\FileCache',
        ],
        'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
        ],
    ],
]

每個應用程式組件都以陣列中的鍵值對形式指定。鍵代表組件 ID,而值代表組件類別名稱或配置

您可以在應用程式中註冊任何組件,並且稍後可以使用表達式 `\Yii::$app->componentID` 全域存取該組件。

有關詳細資訊,請閱讀應用程式組件章節。

controllerMap

此屬性允許您將控制器 ID 對應到任意控制器類別。預設情況下,Yii 根據慣例將控制器 ID 對應到控制器類別(例如,ID `post` 將對應到 `app\controllers\PostController`)。透過配置此屬性,您可以針對特定控制器打破慣例。在以下範例中,`account` 將對應到 `app\controllers\UserController`,而 `article` 將對應到 `app\controllers\PostController`。

[
    'controllerMap' => [
        'account' => 'app\controllers\UserController',
        'article' => [
            'class' => 'app\controllers\PostController',
            'enableCsrfValidation' => false,
        ],
    ],
]

此屬性的陣列鍵代表控制器 ID,而陣列值代表對應的控制器類別名稱或配置

controllerNamespace

此屬性指定應在其中找到控制器類別的預設命名空間。它預設為 `app\controllers`。如果控制器 ID 為 `post`,則依照慣例,對應的控制器類別名稱(不含命名空間)將為 `PostController`,而完整類別名稱將為 `app\controllers\PostController`。

控制器類別也可以位於對應於此命名空間的目錄的子目錄下。例如,給定控制器 ID `admin/post`,對應的完整控制器類別將為 `app\controllers\admin\PostController`。

重要的是,完整控制器類別應為可自動載入的,並且您的控制器類別的實際命名空間應與此屬性的值相符。否則,在存取應用程式時,您將收到「找不到頁面」錯誤。

如果您想打破上述慣例,您可以配置 controllerMap 屬性。

language

此屬性指定應用程式應向終端使用者顯示內容的語言。此屬性的預設值為 `en`,表示英文。如果您的應用程式需要支援多種語言,則應配置此屬性。

此屬性的值決定了各種國際化方面,包括訊息翻譯、日期格式化、數字格式化等。例如,yii\jui\DatePicker 小工具預設會使用此屬性值來決定日曆應以哪種語言顯示以及日期應如何格式化。

建議您以 IETF 語言標籤的形式指定語言。例如,`en` 代表英文,而 `en-US` 代表英文(美國)。

有關此屬性的更多詳細資訊,請參閱國際化章節。

modules

此屬性指定應用程式包含的模組

此屬性採用模組類別或配置的陣列,其中陣列鍵為模組 ID。例如

[
    'modules' => [
        // a "booking" module specified with the module class
        'booking' => 'app\modules\booking\BookingModule',

        // a "comment" module specified with a configuration array
        'comment' => [
            'class' => 'app\modules\comment\CommentModule',
            'db' => 'db',
        ],
    ],
]

有關更多詳細資訊,請參閱模組章節。

name

此屬性指定應用程式名稱,該名稱可能會顯示給終端使用者。與應採用唯一值的 id 屬性不同,此屬性的值主要用於顯示目的;它不需要是唯一的。

如果您的程式碼都沒有使用此屬性,則不一定需要配置它。

params

此屬性指定一個全域可存取的應用程式參數陣列。與其在程式碼中到處使用硬編碼的數字和字串,不如在單一位置將它們定義為應用程式參數,並在需要的地方使用這些參數,這是一種很好的做法。例如,您可以將縮圖影像大小定義為如下所示的參數

[
    'params' => [
        'thumbnail.size' => [128, 128],
    ],
]

然後在您需要在程式碼中使用大小值的地方,您可以簡單地使用如下所示的程式碼

$size = \Yii::$app->params['thumbnail.size'];
$width = \Yii::$app->params['thumbnail.size'][0];

稍後,如果您決定變更縮圖大小,您只需要在應用程式配置中修改它;您不需要觸碰任何相依的程式碼。

sourceLanguage

此屬性指定應用程式程式碼編寫所用的語言。預設值為 `'en-US'`,表示英文(美國)。如果您的程式碼中的文字內容不是英文,則應配置此屬性。

language 屬性一樣,您應該以 IETF 語言標籤的形式配置此屬性。例如,`en` 代表英文,而 `en-US` 代表英文(美國)。

有關此屬性的更多詳細資訊,請參閱國際化章節。

timeZone

提供此屬性是作為設定 PHP 執行階段預設時區的替代方法。透過配置此屬性,您實際上是在呼叫 PHP 函數 date_default_timezone_set()。例如

[
    'timeZone' => 'America/Los_Angeles',
]

有關設定時區的影響的更多詳細資訊,請查看日期格式化章節

version

此屬性指定應用程式的版本。它預設為 `'1.0'`。如果您的程式碼都沒有使用此屬性,則不需要配置它。

實用屬性

本小節中描述的屬性通常不配置,因為它們的預設值來自常見的慣例。但是,如果您想打破慣例,仍然可以配置它們。

charset

此屬性指定應用程式使用的字元集。預設值為 `'UTF-8'`,對於大多數應用程式而言,應保持原樣,除非您正在使用大量非 Unicode 資料的舊系統。

defaultRoute

此屬性指定當請求未指定路由時應用程式應使用的路由。路由可以包含子模組 ID、控制器 ID 和/或動作 ID。例如,`help`、`post/create` 或 `admin/post/create`。如果未給定動作 ID,則此屬性將採用 yii\base\Controller::$defaultAction 中指定的預設值。

對於 Web 應用程式,此屬性的預設值為 `'site'`,這表示應使用 `SiteController` 控制器及其預設動作。因此,如果您在未指定路由的情況下存取應用程式,它將顯示 `app\controllers\SiteController::actionIndex()` 的結果。

對於 命令列應用程式,預設值為 `'help'`,這表示應使用核心指令 yii\console\controllers\HelpController::actionIndex()。因此,如果您在不提供任何引數的情況下執行指令 `yii`,它將顯示說明資訊。

extensions

此屬性指定應用程式安裝和使用的擴充功能清單。預設情況下,它將採用檔案 `@vendor/yiisoft/extensions.php` 傳回的陣列。當您使用 Composer 安裝擴充功能時,會自動產生和維護 `extensions.php` 檔案。因此,在大多數情況下,您不需要配置此屬性。

在您想要手動維護擴充功能的特殊情況下,您可以如下配置此屬性

[
    'extensions' => [
        [
            'name' => 'extension name',
            'version' => 'version number',
            'bootstrap' => 'BootstrapClassName',  // optional, may also be a configuration array
            'alias' => [  // optional
                '@alias1' => 'to/path1',
                '@alias2' => 'to/path2',
            ],
        ],

        // ... more extensions like the above ...

    ],
]

如您所見,此屬性採用擴充功能規格的陣列。每個擴充功能都以包含 `name` 和 `version` 元素的陣列指定。如果擴充功能需要在啟動引導過程中執行,則可以使用啟動引導類別名稱或配置陣列指定 `bootstrap` 元素。擴充功能也可以定義一些別名

layout

此屬性指定在呈現視圖時應使用的預設版面配置的名稱。預設值為 `'main'`,表示應使用版面配置路徑下的版面配置檔案 `main.php`。如果版面配置路徑視圖路徑 都採用預設值,則預設版面配置檔案可以表示為路徑別名 `@app/views/layouts/main.php`。

如果您想預設停用版面配置,則可以將此屬性配置為 `false`,儘管這種情況非常罕見。

layoutPath

此屬性指定應在其中尋找版面配置檔案的路徑。預設值是視圖路徑下的 `layouts` 子目錄。如果 視圖路徑 採用其預設值,則預設版面配置路徑可以表示為路徑別名 `@app/views/layouts`。

您可以將其配置為目錄或路徑別名

runtimePath

此屬性指定可以產生臨時檔案(例如日誌檔案和快取檔案)的路徑。預設值是由別名 `@app/runtime` 表示的目錄。

您可以將其配置為目錄或路徑別名。請注意,runtime path 必須可由執行應用程式的程序寫入。並且該路徑應受到保護,以防止終端使用者存取,因為其下的臨時檔案可能包含敏感資訊。

為了簡化對此路徑的存取,Yii 預先定義了一個名為 `@runtime` 的路徑別名。

viewPath

此屬性指定視圖檔案所在的根目錄。預設值是由別名 `@app/views` 表示的目錄。您可以將其配置為目錄或路徑別名

vendorPath

此屬性指定由 Composer 管理的 vendor 目錄。它包含您的應用程式使用的所有第三方函式庫,包括 Yii 框架。預設值是由別名 @app/vendor 代表的目錄。

您可以將此屬性配置為目錄或路徑別名。當您修改此屬性時,請確保您也相應地調整 Composer 設定。

為了簡化對此路徑的存取,Yii 預定義了一個名為 @vendor 的路徑別名。

enableCoreCommands

此屬性僅由 主控台應用程式 支援。它指定是否應啟用 Yii 發行版本中包含的核心命令。預設值為 true

應用程式事件

應用程式在處理請求的生命週期中會觸發多個事件。您可以在應用程式設定中將事件處理器附加到這些事件,如下所示

[
    'on beforeRequest' => function ($event) {
        // ...
    },
]

on eventName 語法的使用方式在設定章節中說明。

或者,您可以在應用程式實例建立後的啟動過程中附加事件處理器。例如

\Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event) {
    // ...
});

EVENT_BEFORE_REQUEST

此事件在應用程式之前處理請求時觸發。實際事件名稱為 beforeRequest

當此事件觸發時,應用程式實例已被設定和初始化。因此,這是透過事件機制插入您的自訂程式碼以攔截請求處理過程的好地方。例如,在事件處理器中,您可以根據某些參數動態設定 yii\base\Application::$language 屬性。

EVENT_AFTER_REQUEST

此事件在應用程式完成處理請求之後但在發送回應之前觸發。實際事件名稱為 afterRequest

當此事件觸發時,請求處理已完成,您可以藉此機會對請求進行一些後處理或自訂回應。

請注意,response 元件在將回應內容發送給終端使用者時也會觸發一些事件。那些事件是在此事件之後觸發的。

EVENT_BEFORE_ACTION

此事件在每次執行控制器動作之前觸發。實際事件名稱為 beforeAction

事件參數是 yii\base\ActionEvent 的實例。事件處理器可以將 yii\base\ActionEvent::$isValid 屬性設定為 false 以停止執行動作。例如

[
    'on beforeAction' => function ($event) {
        if (some condition) {
            $event->isValid = false;
        } else {
        }
    },
]

請注意,相同的 beforeAction 事件也會由模組控制器觸發。應用程式物件是第一個觸發此事件的物件,接著是模組(如果有的話),最後是控制器。如果事件處理器將 yii\base\ActionEvent::$isValid 設定為 false,則所有後續事件將不會被觸發。

EVENT_AFTER_ACTION

此事件在每次執行控制器動作之後觸發。實際事件名稱為 afterAction

事件參數是 yii\base\ActionEvent 的實例。透過 yii\base\ActionEvent::$result 屬性,事件處理器可以存取或修改動作結果。例如

[
    'on afterAction' => function ($event) {
        if (some condition) {
            // modify $event->result
        } else {
        }
    },
]

請注意,相同的 afterAction 事件也會由模組控制器觸發。這些物件觸發此事件的順序與 beforeAction 相反。也就是說,控制器是第一個觸發此事件的物件,接著是模組(如果有的話),最後是應用程式。

應用程式生命週期

Application Lifecycle

進入腳本正在執行以處理請求時,應用程式將經歷以下生命週期

  1. 進入腳本將應用程式設定載入為陣列。
  2. 進入腳本建立一個新的應用程式實例
  3. 進入腳本呼叫 yii\base\Application::run() 來執行應用程式
    • 觸發 EVENT_BEFORE_REQUEST 事件。
    • 處理請求:將請求解析為路由和相關參數;建立由路由指定的模組、控制器和動作物件;並執行動作。
    • 觸發 EVENT_AFTER_REQUEST 事件。
    • 發送回應給終端使用者。
  4. 進入腳本接收來自應用程式的退出狀態並完成請求處理。

發現錯字或您認為此頁面需要改進嗎?
在 Github 上編輯 !