模塊是獨(dú)立的軟件單元,由模型, 視圖,控制器和其他支持組件組成,終端用戶可以訪問在應(yīng)用主體中已安裝的模塊的控制器,模塊被當(dāng)成小應(yīng)用主體來看待,和應(yīng)用主體不同的是,模塊不能單獨(dú)部署,必須屬于某個(gè)應(yīng)用主體。
模塊被組織成一個(gè)稱為[[yii\base\Module::basePath|base path]]的目錄,在該目錄中有子目錄如controllers
, models
, views
分別為對(duì)應(yīng)控制器,模型,視圖和其他代碼,和應(yīng)用非常類似。如下例子顯示一個(gè)模型的目錄結(jié)構(gòu):
forum/
Module.php 模塊類文件
controllers/ 包含控制器類文件
DefaultController.php default 控制器類文件
models/ 包含模型類文件
views/ 包含控制器視圖文件和布局文件
layouts/ 包含布局文件
default/ 包含 DefaultController 控制器視圖文件
index.php index 視圖文件
每個(gè)模塊都有一個(gè)繼承[[yii\base\Module]]的模塊類,該類文件直接放在模塊的[[yii\base\Module::basePath|base path]]目錄下,并且能被 自動(dòng)加載。當(dāng)一個(gè)模塊被訪問,和 應(yīng)用主體實(shí)例類似會(huì)創(chuàng)建該模塊類唯一實(shí)例,模塊實(shí)例用來幫模塊內(nèi)代碼共享數(shù)據(jù)和組件。
以下示例一個(gè)模塊類大致定義:
namespace app\modules\forum;
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
$this->params['foo'] = 'bar';
// ... 其他初始化代碼 ...
}
}
如果 init()
方法包含很多初始化模塊屬性代碼,可將他們保存在配置 并在init()
中使用以下代碼加載:
public function init()
{
parent::init();
// 從 config.php 加載配置來初始化模塊
\Yii::configure($this, require(__DIR__ . '/config.php'));
}
config.php
配置文件可能包含以下內(nèi)容,類似應(yīng)用主體配置.
<?php
return [
'components' => [
// list of component configurations
],
'params' => [
// list of parameters
],
];
創(chuàng)建模塊的控制器時(shí),慣例是將控制器類放在模塊類命名空間的controllers
子命名空間中,也意味著要將控制器類文件放在模塊[[yii\base\Module::basePath|base path]]目錄中的controllers
子目錄中。例如,上小節(jié)中要在forum
模塊中創(chuàng)建post
控制器,應(yīng)像如下申明控制器類:
namespace app\modules\forum\controllers;
use yii\web\Controller;
class PostController extends Controller
{
// ...
}
可配置[[yii\base\Module::controllerNamespace]]屬性來自定義控制器類的命名空間,如果一些控制器不再該命名空間下,可配置[[yii\base\Module::controllerMap]]屬性讓它們能被訪問,這類似于 應(yīng)用主體配置 所做的。
視圖應(yīng)放在模塊的[[yii\base\Module::basePath|base path]]對(duì)應(yīng)目錄下的 views
目錄,對(duì)于模塊中控制器對(duì)應(yīng)的視圖文件應(yīng)放在 views/ControllerID
目錄下,其中ControllerID
對(duì)應(yīng) 控制器 ID. For example, if 例如,假定控制器類為PostController
,目錄對(duì)應(yīng)模塊[[yii\base\Module::basePath|base path]]目錄下的 views/post
目錄。
模塊可指定 布局,它用在模塊的控制器視圖渲染。布局文件默認(rèn)放在 views/layouts
目錄下,可配置[[yii\base\Module::layout]]屬性指定布局名,如果沒有配置 layout
屬性名,默認(rèn)會(huì)使用應(yīng)用的布局。
要在應(yīng)用中使用模塊,只需要將模塊加入到應(yīng)用主體配置的[[yii\base\Application::modules|modules]]屬性的列表中,如下代碼的應(yīng)用主體配置 使用 forum
模塊:
[
'modules' => [
'forum' => [
'class' => 'app\modules\forum\Module',
// ... 模塊其他配置 ...
],
],
]
[[yii\base\Application::modules|modules]] 屬性使用模塊配置數(shù)組,每個(gè)數(shù)組鍵為模塊 ID,它標(biāo)識(shí)該應(yīng)用中唯一的模塊,數(shù)組的值為用來創(chuàng)建模塊的 配置。
和訪問應(yīng)用的控制器類似,路由 也用在模塊中控制器的尋址,模塊中控制器的路由必須以模塊 ID 開始,接下來為控制器 ID 和操作 ID。例如,假定應(yīng)用使用一個(gè)名為 forum
模塊,路由forum/post/index
代表模塊中 post
控制器的 index
操作,如果路由只包含模塊 ID,默認(rèn)為 default
的[[yii\base\Module::defaultRoute]] 屬性來決定使用哪個(gè)控制器/操作,也就是說路由 forum
可能代表 forum
模塊的 default
控制器。
在模塊中,可能經(jīng)常需要獲取模塊類的實(shí)例來訪問模塊 ID,模塊參數(shù),模塊組件等,可以使用如下語句來獲?。?/p>
$module = MyModuleClass::getInstance();
其中 MyModuleClass
對(duì)應(yīng)你想要的模塊類,getInstance()
方法返回當(dāng)前請(qǐng)求的模塊類實(shí)例,如果模塊沒有被請(qǐng)求,該方法會(huì)返回空,注意不需要手動(dòng)創(chuàng)建一個(gè)模塊類,因?yàn)槭謩?dòng)創(chuàng)建的和 Yii 處理請(qǐng)求時(shí)自動(dòng)創(chuàng)建的不同。
補(bǔ)充: 當(dāng)開發(fā)模塊時(shí),你不能假定模塊使用固定的 ID,因?yàn)樵趹?yīng)用或其他沒模塊中,模塊可能會(huì)對(duì)應(yīng)到任意的 ID,為了獲取模塊 ID,應(yīng)使用上述代碼獲取模塊實(shí)例,然后通過
$module->id
獲取模塊 ID。
也可以使用如下方式訪問模塊實(shí)例:
// 獲取 ID 為 "forum" 的模塊
$module = \Yii::$app->getModule('forum');
// 獲取處理當(dāng)前請(qǐng)求控制器所屬的模塊
$module = \Yii::$app->controller->module;
第一種方式僅在你知道模塊 ID 的情況下有效,第二種方式在你知道處理請(qǐng)求的控制器下使用。
一旦獲取到模塊實(shí)例,可訪問注冊(cè)到模塊的參數(shù)和組件,例如:
$maxPostCount = $module->params['maxPostCount'];
有些模塊在每個(gè)請(qǐng)求下都有運(yùn)行, [[yii\debug\Module|debug]] 模塊就是這種,為此將這種模塊加入到應(yīng)用主體的 [[yii\base\Application::bootstrap|bootstrap]] 屬性中。
例如,如下示例的應(yīng)用主體配置會(huì)確保debug
模塊每次都被加載:
[
'bootstrap' => [
'debug',
],
'modules' => [
'debug' => 'yii\debug\Module',
],
]
模塊可無限級(jí)嵌套,也就是說,模塊可以包含另一個(gè)包含模塊的模塊,我們稱前者為父模塊,后者為子模塊,子模塊必須在父模塊的[[yii\base\Module::modules|modules]]屬性中申明,例如:
namespace app\modules\forum;
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
$this->modules = [
'admin' => [
// 此處應(yīng)考慮使用一個(gè)更短的命名空間
'class' => 'app\modules\forum\modules\admin\Module',
],
];
}
}
在嵌套模塊中的控制器,它的路由應(yīng)包含它所有祖先模塊的 ID,例如forum/admin/dashboard/index
代表在模塊forum
中子模塊admin
中dashboard
控制器的index
操作。
模塊在大型項(xiàng)目中常備使用,這些項(xiàng)目的特性可分組,每個(gè)組包含一些強(qiáng)相關(guān)的特性,每個(gè)特性組可以做成一個(gè)模塊由特定的開發(fā)人員和開發(fā)組來開發(fā)和維護(hù)。
在特性組上,使用模塊也是重用代碼的好方式,一些常用特性,如用戶管理,評(píng)論管理,可以開發(fā)成模塊,這樣在相關(guān)項(xiàng)目中非常容易被重用。