模組是獨立的軟體單元,由模型, 視圖, 控制器和其他支援元件組成, 終端使用者可以存取在應用主體中已安裝的模組的控制器, 模組被當成小應用主體來看待,和應用主體不同的是, 模組不能單獨部署,必須屬於某個應用程式主體。
創建模組
模組被組織成一個稱為[[yiibaseModule::basePath|base path]]的目錄, 在該目錄中有子目錄如controllers,models,views分別為對應控制器,模型,視圖和其他代碼,和應用非常類似。 如下範例顯示一個模型的目錄結構:
forum/ Module.php 模块类文件 controllers/ 包含控制器类文件 DefaultController.php default 控制器类文件 models/ 包含模型类文件 views/ 包含控制器视图文件和布局文件 layouts/ 包含布局文件 default/ 包含DefaultController控制器视图文件 index.php index视图文件
模組類
每個模組都有一個繼承[[yiibaseModule]]的模組類,該類文件直接放在模組的[[yiibaseModule::basePath|base path] ]目錄下, 並且能自動載入。當一個模組被訪問,和 應用主體實例 類似會創建該模組類別唯一實例,模組實例用來幫模組內程式碼共享資料和組件。
以下範例一個模組類別大致定義:
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設定檔可能包含以下內容,類似應用主體配置.
<?php return [ 'components' => [ // list of component configurations ], 'params' => [ // list of parameters ], ];
模組中的控制器
創建模組的控制器時,慣例是將控制器類別放在模組類命名空間的controllers子命名空間中, 也意味著要將控制器類別檔案放在模組[[yiibaseModule::basePath|base path]]目錄中的controllers子目錄中。 例如,上小節要在forum模組中建立post控制器,應像如下申明控制器類別:
namespace app\modules\forum\controllers; use yii\web\Controller; class PostController extends Controller { // ... }
可設定[[yiibaseModule::controllerNamespace]]屬性來自訂控制器類別的命名空間, 如果某些控制器不再該命名空間下,可配置[[yiibaseModule::controllerMap]]屬性讓它們能被訪問, 這類似於應用主體配置所做的。
模組中的視圖
視圖應放在模組的[[yiibaseModule::basePath|base path]]對應目錄下的views目錄, 模組中控制器對應的視圖檔案應放在views/ControllerID目錄下,其中ControllerID對應控制器ID. For example, if 例如,假定控制器類別為PostController,目錄對應模組[[yiibaseModule::basePath|base path]]目錄下的views/post目錄。
模組可指定 佈局,它用在模組的控制器視圖渲染。 佈局檔案預設放在views/layouts目錄下,可設定[[yiibaseModule::layout]]屬性指定佈局名, 如果沒有配置layout屬性名,預設會使用套用的佈局。
使用模組
要在應用程式中使用模組,只需要將模組加入到應用程式主體設定的[[yiibaseApplication::modules|modules]]屬性的清單中, 如下程式碼的應用程式主體設定使用forum模組:
[ 'modules' => [ 'forum' => [ 'class' => 'app\modules\forum\Module', // ... 模块其他配置 ... ], ], ]
[[yiibaseApplication::modules|modules]] 屬性使用模組配置數組,每個數組鍵為模組ID, 它標識該應用程式中唯一的模組,數組的值為用來創建模組的配置。
路由
和存取應用的控制器類似,路由 也用在模組中控制器的尋址, 模組中控制器的路由必須以模組ID開始,接下來為控制器ID和操作ID。 例如,假設應用程式使用一個名為forum模組,路由forum/post/index代表模組中post控制器的index操作, 如果路由只包含模組ID,預設為default的[[yiibaseModule::defaultRoute]] 屬性來決定使用哪個控制器/操作, 也就是說路由forum可能代表forum模組的default控制器。
存取模組
在模組中,可能經常需要取得模組類別的實例來存取模組ID,模組參數,模組元件等, 可以使用如下語句來取得:
$module = MyModuleClass::getInstance();
其中MyModuleClass對應你想要的模組類, getInstance()方法傳回目前要求的模組類實例, 如果模組沒有被要求,方法會傳回空,注意不需要手動建立一個模組類,因為手動建立的和Yii處理請求時自動建立的不同。
補充: 當開發模組時,你不能假定模組使用固定的ID,因為在應用或其他沒模組中,模組可能會對應到任意的ID, 為了獲取模組ID,應使用上述程式碼取得模組實例,然後透過$module->id取得模組ID。
也可以使用以下方式存取模組實例:
// 获取ID为 "forum" 的模块 $module = \Yii::$app->getModule('forum'); // 获取处理当前请求控制器所属的模块 $module = \Yii::$app->controller->module;
第一种方式仅在你知道模块ID的情况下有效,第二种方式在你知道处理请求的控制器下使用。
一旦获取到模块实例,可访问注册到模块的参数和组件,例如:
$maxPostCount = $module->params['maxPostCount'];
引导启动模块
有些模块在每个请求下都有运行, [[yii\debug\Module|debug]] 模块就是这种, 为此将这种模块加入到应用主体的 [[yii\base\Application::bootstrap|bootstrap]] 属性中。
例如,如下示例的应用主体配置会确保debug模块每次都被加载:
[ 'bootstrap' => [ 'debug', ], 'modules' => [ 'debug' => 'yii\debug\Module', ], ]
模块嵌套
模块可无限级嵌套,也就是说,模块可以包含另一个包含模块的模块,我们称前者为父模块,后者为子模块, 子模块必须在父模块的[[yii\base\Module::modules|modules]]属性中申明,例如:
namespace app\modules\forum; class Module extends \yii\base\Module { public function init() { parent::init(); $this->modules = [ 'admin' => [ // 此处应考虑使用一个更短的命名空间 'class' => 'app\modules\forum\modules\admin\Module', ], ]; } }
在嵌套模块中的控制器,它的路由应包含它所有祖先模块的ID,例如forum/admin/dashboard/index代表 在模块forum中子模块admin中dashboard控制器的index操作。
最佳实践
模块在大型项目中常备使用,这些项目的特性可分组,每个组包含一些强相关的特性, 每个特性组可以做成一个模块由特定的开发人员和开发组来开发和维护。
在特性组上,使用模块也是重用代码的好方式,一些常用特性,如用户管理,评论管理,可以开发成模块, 这样在相关项目中非常容易被重用。