應(yīng)用(Applications)

2018-02-24 15:40 更新

應(yīng)用主體

應(yīng)用主體是管理 Yii 應(yīng)用系統(tǒng)整體結(jié)構(gòu)和生命周期的對(duì)象。 每個(gè)Yii應(yīng)用系統(tǒng)只能包含一個(gè)應(yīng)用主體,應(yīng)用主體在?入口腳本?中創(chuàng)建并能通過(guò)表達(dá)式?\Yii::$app?全局范圍內(nèi)訪問(wèn)。

補(bǔ)充: 當(dāng)我們說(shuō)"一個(gè)應(yīng)用",它可能是一個(gè)應(yīng)用主體對(duì)象,也可能是一個(gè)應(yīng)用系統(tǒng),是根據(jù)上下文來(lái)決定[譯:中文為避免歧義,Application翻譯為應(yīng)用主體]。

Yii有兩種應(yīng)用主體: yii\web\Application and yii\console\Application, 如名稱(chēng)所示,前者主要處理網(wǎng)頁(yè)請(qǐng)求,后者處理控制臺(tái)請(qǐng)求。

應(yīng)用主體配置

如下所示,當(dāng)?入口腳本?創(chuàng)建了一個(gè)應(yīng)用主體,它會(huì)加載一個(gè)?配置?文件并傳給應(yīng)用主體。

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

// 加載應(yīng)用主體配置
$config = require(__DIR__ . '/../config/web.php');

// 實(shí)例化應(yīng)用主體、配置應(yīng)用主體
(new yii\web\Application($config))->run();

類(lèi)似其他?配置?文件, 應(yīng)用主體配置文件標(biāo)明如何設(shè)置應(yīng)用對(duì)象初始屬性。 由于應(yīng)用主體配置比較復(fù)雜,一般保存在多個(gè)類(lèi)似如上web.php的?配置文件?當(dāng)中。

應(yīng)用主體屬性

應(yīng)用主體配置文件中有許多重要的屬性要配置,這些屬性指定應(yīng)用主體的運(yùn)行環(huán)境。 比如,應(yīng)用主體需要知道如何加載?控制器?,臨時(shí)文件保存到哪兒等等。 以下我們簡(jiǎn)述這些屬性。

必要屬性

在一個(gè)應(yīng)用中,至少要配置2個(gè)屬性: yii\base\Application::id 和 yii\base\Application::basePath。

yii\base\Application::id

yii\base\Application::id 屬性用來(lái)區(qū)分其他應(yīng)用的唯一標(biāo)識(shí)ID。主要給程序使用。 為了方便協(xié)作,最好使用數(shù)字作為應(yīng)用主體ID,但不強(qiáng)制要求為數(shù)字。

yii\base\Application::basePath

yii\base\Application::basePath 指定該應(yīng)用的根目錄。根目錄包含應(yīng)用系統(tǒng)所有受保護(hù)的源代碼。 在根目錄下可以看到對(duì)應(yīng)MVC設(shè)計(jì)模式的models,?views,?controllers等子目錄。

可以使用路徑或?路徑別名?來(lái)在配置 yii\base\Application::basePath 屬性。 兩種格式所對(duì)應(yīng)的目錄都必須存在,否則系統(tǒng)會(huì)拋出一個(gè)異常。 系統(tǒng)會(huì)使用?realpath()?函數(shù)規(guī)范化配置的路徑.

yii\base\Application::basePath 屬性經(jīng)常用于派生一些其他重要路徑(如runtime路徑),因此,系統(tǒng)預(yù)定義?@app?代表這個(gè)路徑。 派生路徑可以通過(guò)這個(gè)別名組成(如@app/runtime代表runtime的路徑)。

重要屬性

本小節(jié)所描述的屬性通常需要設(shè)置,因?yàn)椴煌膽?yīng)用屬性不同。

yii\base\Application::aliases

該屬性允許你用一個(gè)數(shù)組定義多個(gè)?別名。數(shù)組的key為別名名稱(chēng),值為對(duì)應(yīng)的路徑。例如:

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

使用這個(gè)屬性來(lái)定義別名,代替 Yii::setAlias() 方法來(lái)設(shè)置。

yii\base\Application::bootstrap

這個(gè)屬性很實(shí)用,它允許你用數(shù)組指定啟動(dòng)階段yii\base\Application::bootstrap()需要運(yùn)行的組件。 比如,如果你希望一個(gè)?模塊?自定義URL 規(guī)則,你可以將模塊ID加入到bootstrap數(shù)組中。

屬性中的每個(gè)組件需要指定以下一項(xiàng):

  • 應(yīng)用?組件?ID.
  • 模塊?ID.
  • 類(lèi)名.
  • 配置數(shù)組.
  • 創(chuàng)建并返回一個(gè)組件的無(wú)名稱(chēng)函數(shù).

例如:

[
    'bootstrap' => [
        // 應(yīng)用組件ID或模塊ID
        'demo',

        // 類(lèi)名
        'app\components\Profiler',

        // 配置數(shù)組
        [
            'class' => 'app\components\Profiler',
            'level' => 3,
        ],

        // 無(wú)名稱(chēng)函數(shù)
        function () {
            return new app\components\Profiler();
        }
    ],
]

補(bǔ)充: 如果模塊ID和應(yīng)用組件ID同名,優(yōu)先使用應(yīng)用組件ID,如果你想用模塊ID,可以使用如下無(wú)名稱(chēng)函數(shù)返回模塊ID。?`````php [

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

]?`````

在啟動(dòng)階段,每個(gè)組件都會(huì)實(shí)例化。如果組件類(lèi)實(shí)現(xiàn)接口 yii\base\BootstrapInterface,也會(huì)調(diào)用 yii\base\BootstrapInterface::bootstrap() 方法。

舉一個(gè)實(shí)際的例子,Basic Application Template?應(yīng)用主體配置中, 開(kāi)發(fā)環(huán)境下會(huì)在啟動(dòng)階段運(yùn)行?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';
}

注: 啟動(dòng)太多的組件會(huì)降低系統(tǒng)性能,因?yàn)槊看握?qǐng)求都需要重新運(yùn)行啟動(dòng)組件,因此謹(jǐn)慎配置啟動(dòng)組件。

yii\web\Application::catchAll

該屬性?xún)H yii\web\Application 網(wǎng)頁(yè)應(yīng)用支持。 它指定一個(gè)要處理所有用戶(hù)請(qǐng)求的?控制器方法,通常在維護(hù)模式下使用,同一個(gè)方法處理所有用戶(hù)請(qǐng)求。

該配置為一個(gè)數(shù)組,第一項(xiàng)指定動(dòng)作的路由,剩下的數(shù)組項(xiàng)(key-value 成對(duì))指定傳遞給動(dòng)作的參數(shù),例如:

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

yii\base\Application::components

這是最重要的屬性,它允許你注冊(cè)多個(gè)在其他地方使用的應(yīng)用組件. 例如

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

每一個(gè)應(yīng)用組件指定一個(gè)key-value對(duì)的數(shù)組,key代表組件ID,value代表組件類(lèi)名或?配置。

在應(yīng)用中可以任意注冊(cè)組件,并可以通過(guò)表達(dá)式?\Yii::$app->ComponentID?全局訪問(wèn)。

詳情請(qǐng)閱讀?應(yīng)用組件?一節(jié).

yii\base\Application::controllerMap

該屬性允許你指定一個(gè)控制器ID到任意控制器類(lèi)。Yii遵循一個(gè)默認(rèn)的?規(guī)則指定控制器ID到任意控制器類(lèi)(如post對(duì)應(yīng)app\controllers\PostController)。 通過(guò)配置這個(gè)屬性,可以打破這個(gè)默認(rèn)規(guī)則,在下面的例子中,account對(duì)應(yīng)到app\controllers\UserController,?article?對(duì)應(yīng)到?app\controllers\PostController。

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

數(shù)組的鍵代表控制器ID,數(shù)組的值代表對(duì)應(yīng)的類(lèi)名。

yii\base\Application::controllerNamespace

該屬性指定控制器類(lèi)默認(rèn)的命名空間,默認(rèn)為app\controllers。比如控制器ID為?post?默認(rèn)對(duì)應(yīng)?PostController?(不帶命名空間), 類(lèi)全名為?app\controllers\PostController

控制器類(lèi)文件可能放在這個(gè)命名空間對(duì)應(yīng)目錄的子目錄下, 例如,控制器ID?admin/post?對(duì)應(yīng)的控制器類(lèi)全名為app\controllers\admin\PostController。

控制器類(lèi)全面能被?自動(dòng)加載,這點(diǎn)是非常重要的,控制器類(lèi)的實(shí)際命名空間對(duì)應(yīng)這個(gè)屬性, 否則,訪問(wèn)時(shí)你會(huì)收到"Page Not Found"[譯:頁(yè)面找不到]。

如果你想打破上述的規(guī)則,可以配置?controllerMap?屬性。

yii\base\Application::language

該屬性指定應(yīng)用展示給終端用戶(hù)的語(yǔ)言,默認(rèn)為?en?標(biāo)識(shí)英文。如果需要之前其他語(yǔ)言可以配置該屬性。

該屬性影響各種?國(guó)際化?,包括信息翻譯、日期格式、數(shù)字格式等。 例如 yii\jui\DatePicker 小部件會(huì)根據(jù)該屬性展示對(duì)應(yīng)語(yǔ)言的日歷以及日期格式。

推薦遵循?IETF language tag?來(lái)設(shè)置語(yǔ)言,例如?en?代表英文,?en-US?代表英文(美國(guó)).

該屬性的更多信息可參考?國(guó)際化?一節(jié).

yii\base\Application::modules

該屬性指定應(yīng)用所包含的?模塊。

該屬性使用數(shù)組包含多個(gè)模塊類(lèi)?配置,數(shù)組的鍵為模塊ID,例:

[
    'modules' => [
        // "booking" 模塊以及對(duì)應(yīng)的類(lèi)
        'booking' => 'app\modules\booking\BookingModule',

        // "comment" 模塊以及對(duì)應(yīng)的配置數(shù)組
        'comment' => [
            'class' => 'app\modules\comment\CommentModule',
            'db' => 'db',
        ],
    ],
]

更多詳情請(qǐng)參考?模塊?一節(jié)。

yii\base\Application::name

該屬性指定你可能想展示給終端用戶(hù)的應(yīng)用名稱(chēng),不同于需要唯一性的 yii\base\Application::id 屬性, 該屬性可以不唯一,該屬性用于顯示應(yīng)用的用途。

如果其他地方的代碼沒(méi)有用到,可以不配置該屬性。

yii\base\Application::params

該屬性為一個(gè)數(shù)組,指定可以全局訪問(wèn)的參數(shù),代替程序中硬編碼的數(shù)字和字符,應(yīng)用中的參數(shù)定義到一個(gè)單獨(dú)的文件并隨時(shí)可以訪問(wèn)是一個(gè)好習(xí)慣。 例如用參數(shù)定義縮略圖的長(zhǎng)寬如下:

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

然后簡(jiǎn)單的使用如下代碼即可獲取到你需要的長(zhǎng)寬參數(shù):

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

以后想修改縮略圖長(zhǎng)寬,只需要修改該參數(shù)而不需要相關(guān)的代碼。

yii\base\Application::sourceLanguage

該屬性指定應(yīng)用代碼的語(yǔ)言,默認(rèn)為?'en-US'?標(biāo)識(shí)英文(美國(guó)),如果應(yīng)用不是英文請(qǐng)修改該屬性。

和?語(yǔ)言?屬性類(lèi)似,配置該屬性需遵循?IETF language tag. 例如?en?代表英文,?en-US?代表英文(美國(guó))。

該屬性的更多信息可參考?國(guó)際化?一節(jié).

yii\base\Application::timeZone

該屬性提供一種方式修改PHP運(yùn)行環(huán)境中的默認(rèn)時(shí)區(qū),配置該屬性本質(zhì)上就是調(diào)用PHP函數(shù)?date_default_timezone_set(),例如:

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

yii\base\Application::version

該屬性指定應(yīng)用的版本,默認(rèn)為'1.0',其他代碼不使用的話(huà)可以不配置。

實(shí)用屬性

本小節(jié)描述的屬性不經(jīng)常設(shè)置,通常使用系統(tǒng)默認(rèn)值。如果你想改變默認(rèn)值,可以配置這些屬性。

yii\base\Application::charset

該屬性指定應(yīng)用使用的字符集,默認(rèn)值為?'UTF-8',絕大部分應(yīng)用都在使用,除非已有的系統(tǒng)大量使用非unicode數(shù)據(jù)才需要更改該屬性。

yii\base\Application::defaultRoute

該屬性指定未配置的請(qǐng)求的響應(yīng)?路由?規(guī)則,路由規(guī)則可能包含模塊ID,控制器ID,動(dòng)作ID。 例如help,?post/create,admin/post/create,如果動(dòng)作ID沒(méi)有指定,會(huì)使用yii\base\Controller::defaultAction中指定的默認(rèn)值。

對(duì)于 yii\web\Application 網(wǎng)頁(yè)應(yīng)用,默認(rèn)值為?'site'?對(duì)應(yīng)?SiteController?控制器,并使用默認(rèn)的動(dòng)作。 因此你不帶路由的訪問(wèn)應(yīng)用,默認(rèn)會(huì)顯示?app\controllers\SiteController::actionIndex()?的結(jié)果。

對(duì)于 yii\console\Application 控制臺(tái)應(yīng)用, 默認(rèn)值為?'help'?對(duì)應(yīng) yii\console\controllers\HelpController::actionIndex()。 因此,如果執(zhí)行的命令不帶參數(shù),默認(rèn)會(huì)顯示幫助信息。

yii\base\Application::extensions

該屬性用數(shù)組列表指定應(yīng)用安裝和使用的?擴(kuò)展,默認(rèn)使用@vendor/yiisoft/extensions.php文件返回的數(shù)組。 當(dāng)你使用?Composer安裝擴(kuò)展,extensions.php?會(huì)被自動(dòng)生成和維護(hù)更新。 所以大多數(shù)情況下,不需要配置該屬性。

特殊情況下你想自己手動(dòng)維護(hù)擴(kuò)展,可以參照如下配置該屬性:

[
    'extensions' => [
        [
            'name' => 'extension name',
            'version' => 'version number',
            'bootstrap' => 'BootstrapClassName',  // 可選配,可為配置數(shù)組
            'alias' => [  // 可選配
                '@alias1' => 'to/path1',
                '@alias2' => 'to/path2',
            ],
        ],

        // ... 更多像上面的擴(kuò)展 ...

    ],
]

如上所示,該屬性包含一個(gè)擴(kuò)展定義數(shù)組,每個(gè)擴(kuò)展為一個(gè)包含?name?和?version?項(xiàng)的數(shù)組。 如果擴(kuò)展要在?引導(dǎo)啟動(dòng)?階段運(yùn)行,需要配置?bootstrap以及對(duì)應(yīng)的引導(dǎo)啟動(dòng)類(lèi)名或?configuration?數(shù)組。 擴(kuò)展也可以定義?別名

yii\base\Application::layout

該屬性指定渲染?視圖?默認(rèn)使用的布局名字,默認(rèn)值為?'main'?對(duì)應(yīng)布局路徑下的?main.php?文件, 如果?布局路徑?和?視圖路徑?都是默認(rèn)值,默認(rèn)布局文件可以使用路徑別名@app/views/layouts/main.php

如果不想設(shè)置默認(rèn)布局文件,可以設(shè)置該屬性為?false,這種做法比較罕見(jiàn)。

yii\base\Application::layoutPath

該屬性指定查找布局文件的路徑,默認(rèn)值為?視圖路徑?下的?layouts?子目錄。 如果?視圖路徑?使用默認(rèn)值,默認(rèn)的布局路徑別名為@app/views/layouts。

該屬性需要配置成一個(gè)目錄或 路徑?別名

yii\base\Application::runtimePath

該屬性指定臨時(shí)文件如日志文件、緩存文件等保存路徑,默認(rèn)值為帶別名的?@app/runtime

可以配置該屬性為一個(gè)目錄或者路徑?別名,注意應(yīng)用運(yùn)行時(shí)有對(duì)該路徑的寫(xiě)入權(quán)限, 以及終端用戶(hù)不能訪問(wèn)該路徑因?yàn)榕R時(shí)文件可能包含一些敏感信息。

為了簡(jiǎn)化訪問(wèn)該路徑,Yii預(yù)定義別名?@runtime?代表該路徑。

yii\base\Application::viewPath

該路徑指定視圖文件的根目錄,默認(rèn)值為帶別名的?@app/views,可以配置它為一個(gè)目錄或者路徑?別名.

yii\base\Application::vendorPath

該屬性指定?Composer?管理的供應(yīng)商路徑,該路徑包含應(yīng)用使用的包括Yii框架在內(nèi)的所有第三方庫(kù)。 默認(rèn)值為帶別名的@app/vendor?。

可以配置它為一個(gè)目錄或者路徑?別名,當(dāng)你修改時(shí),務(wù)必修改對(duì)應(yīng)的 Composer 配置。

為了簡(jiǎn)化訪問(wèn)該路徑,Yii預(yù)定義別名?@vendor?代表該路徑。

yii\console\Application::enableCoreCommands

該屬性?xún)H yii\console\Application 控制臺(tái)應(yīng)用支持, 用來(lái)指定是否啟用Yii中的核心命令,默認(rèn)值為?true。

應(yīng)用事件

應(yīng)用在處理請(qǐng)求過(guò)程中會(huì)觸發(fā)事件,可以在配置文件配置事件處理代碼,如下所示:

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

on eventName?語(yǔ)法的用法在?Configurations?一節(jié)有詳細(xì)描述.

另外,在應(yīng)用主體實(shí)例化后,你可以在引導(dǎo)啟動(dòng)?階段附加事件處理代碼,例如:

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

yii\base\Application::EVENT_BEFORE_REQUEST

該事件在應(yīng)用處理請(qǐng)求before之前,實(shí)際的事件名為?beforeRequest

在事件觸發(fā)前,應(yīng)用主體已經(jīng)實(shí)例化并配置好了,所以通過(guò)事件機(jī)制將你的代碼嵌入到請(qǐng)求處理過(guò)程中非常不錯(cuò)。 例如在事件處理中根據(jù)某些參數(shù)動(dòng)態(tài)設(shè)置yii\base\Application::language語(yǔ)言屬性。

yii\base\Application::EVENT_AFTER_REQUEST

該事件在應(yīng)用處理請(qǐng)求after之后但在返回響應(yīng)before之前觸發(fā),實(shí)際的事件名為afterRequest。

該事件觸發(fā)時(shí),請(qǐng)求已經(jīng)被處理完,可以做一些請(qǐng)求后處理或自定義響應(yīng)。

注意 yii\web\Response 組件在發(fā)送響應(yīng)給終端用戶(hù)時(shí)也會(huì)觸發(fā)一些事件,這些事件都在本事件after之后觸發(fā)。

yii\base\Application::EVENT_BEFORE_ACTION

該事件在每個(gè)?控制器動(dòng)作?運(yùn)行before之前會(huì)被觸發(fā),實(shí)際的事件名為?beforeAction.

事件的參數(shù)為一個(gè) yii\base\ActionEvent 實(shí)例, 事件處理中可以設(shè)置yii\base\ActionEvent::isValid 為?false?停止運(yùn)行后續(xù)動(dòng)作,例如:

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

注意?模塊?和?控制器?都會(huì)觸發(fā)?beforeAction?事件。 應(yīng)用主體對(duì)象首先觸發(fā)該事件,然后模塊觸發(fā)(如果存在模塊),最后控制器觸發(fā)。 任何一個(gè)事件處理中設(shè)置 yii\base\ActionEvent::isValid 設(shè)置為?false?會(huì)停止觸發(fā)后面的事件。

yii\base\Application::EVENT_AFTER_ACTION

該事件在每個(gè)?控制器動(dòng)作?運(yùn)行after之后會(huì)被觸發(fā),實(shí)際的事件名為?afterAction.

該事件的參數(shù)為 yii\base\ActionEvent 實(shí)例,通過(guò)yii\base\ActionEvent::result屬性, 事件處理可以訪問(wèn)和修改動(dòng)作的結(jié)果。例如:

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

注意?模塊?和?控制器?都會(huì)觸發(fā)?afterAction?事件。 這些對(duì)象的觸發(fā)順序和?beforeAction?相反,也就是說(shuō),控制器最先觸發(fā),然后是模塊(如果有模塊),最后為應(yīng)用主體。

應(yīng)用主體生命周期

當(dāng)運(yùn)行?入口腳本?處理請(qǐng)求時(shí),應(yīng)用主體會(huì)經(jīng)歷以下生命周期:

  1. 入口腳本加載應(yīng)用主體配置數(shù)組。
  2. 入口腳本創(chuàng)建一個(gè)應(yīng)用主體實(shí)例:
    • 調(diào)用 yii\base\Application::preInit() 配置幾個(gè)高級(jí)別應(yīng)用主體屬性,比如yii\base\Application::basePath。
    • 注冊(cè) yii\base\Application::errorHandler 錯(cuò)誤處理方法.
    • 配置應(yīng)用主體屬性.
    • 調(diào)用 yii\base\Application::init() 初始化,該函數(shù)會(huì)調(diào)用 yii\base\Application::bootstrap() 運(yùn)行引導(dǎo)啟動(dòng)組件.
  3. 入口腳本調(diào)用 yii\base\Application::run() 運(yùn)行應(yīng)用主體:
    • 觸發(fā) yii\base\Application::EVENT_BEFORE_REQUEST 事件。
    • 處理請(qǐng)求:解析請(qǐng)求?路由?和相關(guān)參數(shù);創(chuàng)建路由指定的模塊、控制器和動(dòng)作對(duì)應(yīng)的類(lèi),并運(yùn)行動(dòng)作。
    • 觸發(fā) yii\base\Application::EVENT_AFTER_REQUEST 事件。
    • 發(fā)送響應(yīng)到終端用戶(hù).
  4. 入口腳本接收應(yīng)用主體傳來(lái)的退出狀態(tài)并完成請(qǐng)求的處理。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)