模組是自我包含的軟體單元,由模型、視圖、控制器和其他支援組件組成。當模組安裝在應用程式中時,終端使用者可以存取模組的控制器。由於這些原因,模組通常被視為迷你應用程式。模組與應用程式的不同之處在於模組不能單獨部署,並且必須駐留在應用程式中。
模組的組織形式是一個目錄,稱為模組的基底路徑。在該目錄中,有子目錄,例如 controllers
、models
、views
,它們像在應用程式中一樣,包含控制器、模型、視圖和其他程式碼。以下範例顯示模組內的內容
forum/
Module.php the module class file
controllers/ containing controller class files
DefaultController.php the default controller class file
models/ containing model class files
views/ containing controller view and layout files
layouts/ containing layout view files
default/ containing view files for DefaultController
index.php the index view file
每個模組都應該有一個唯一的模組類別,它繼承自 yii\base\Module。該類別應該直接位於模組的基底路徑下,並且應該是可自動載入的。當存取模組時,將會建立相應模組類別的單一實例。與應用程式實例類似,模組實例用於在模組內的程式碼之間共享資料和組件。
以下是一個模組類別的範例
namespace app\modules\forum;
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
$this->params['foo'] = 'bar';
// ... other initialization code ...
}
}
如果 init()
方法包含大量初始化模組屬性的程式碼,您也可以將它們以配置的形式儲存,並使用以下程式碼在 init()
中載入它
public function init()
{
parent::init();
// initialize the module with the configuration loaded from config.php
\Yii::configure($this, require __DIR__ . '/config.php');
}
其中配置檔案 config.php
可能包含以下內容,類似於應用程式配置中的內容。
<?php
return [
'components' => [
// list of component configurations
],
'params' => [
// list of parameters
],
];
在模組中建立控制器時,慣例是將控制器類別放在模組類別命名空間的 controllers
子命名空間下。這也意味著控制器類別檔案應該放在模組基底路徑內的 controllers
目錄中。例如,要在上一個小節中顯示的 forum
模組中建立 post
控制器,您應該像下面這樣宣告控制器類別
namespace app\modules\forum\controllers;
use yii\web\Controller;
class PostController extends Controller
{
// ...
}
您可以透過配置 yii\base\Module::$controllerNamespace 屬性來自訂控制器類別的命名空間。如果某些控制器位於此命名空間之外,您可以透過配置 yii\base\Module::$controllerMap 屬性使它們可存取,類似於在應用程式中所做的事情。
模組中的視圖應放在模組基底路徑內的 views
目錄中。對於模組中的控制器呈現的視圖,它們應放在 views/ControllerID
目錄下,其中 ControllerID
指的是控制器 ID。例如,如果控制器類別是 PostController
,則目錄將是模組基底路徑內的 views/post
。
模組可以指定一個佈局,該佈局應用於模組控制器呈現的視圖。佈局預設應放在 views/layouts
目錄中,您應該配置 yii\base\Module::$layout 屬性以指向佈局名稱。如果您未配置 layout
屬性,則將改為使用應用程式的佈局。
您的模組也可以宣告命令,這些命令將透過控制台模式提供。
為了使命令列公用程式看到您的命令,您需要在控制台模式下執行 Yii 時更改 yii\base\Module::$controllerNamespace 屬性,並將其指向您的命令命名空間。
實現此目的的一種方法是在模組的 init()
方法中測試 Yii 應用程式的實例類型
public function init()
{
parent::init();
if (Yii::$app instanceof \yii\console\Application) {
$this->controllerNamespace = 'app\modules\forum\commands';
}
}
然後,您的命令將可從命令列使用以下路由
yii <module_id>/<command>/<sub_command>
要在應用程式中使用模組,只需透過在應用程式的 modules 屬性中列出模組來配置應用程式。 應用程式配置中的以下程式碼使用了 forum
模組
[
'modules' => [
'forum' => [
'class' => 'app\modules\forum\Module',
// ... other configurations for the module ...
],
],
]
資訊:要連接模組的控制台命令,您還需要將其包含在 控制台應用程式配置中
modules 屬性接受模組配置的陣列。每個陣列鍵代表一個模組 ID,它唯一地識別應用程式中所有模組中的模組,並且相應的陣列值是用於建立模組的配置。
與存取應用程式中的控制器類似,路由用於尋址模組中的控制器。模組內控制器的路由必須以模組 ID 開頭,後跟控制器 ID 和 操作 ID。例如,如果應用程式使用名為 forum
的模組,則路由 forum/post/index
將表示模組中 post
控制器的 index
操作。如果路由僅包含模組 ID,則預設為 default
的 yii\base\Module::$defaultRoute 屬性將決定應使用哪個控制器/操作。這表示路由 forum
將表示 forum
模組中的 default
控制器。
模組的 URL 管理器規則應在 yii\web\UrlManager::parseRequest() 觸發之前新增。這表示在模組的 init()
中執行它將不起作用,因為模組將在路由已處理時初始化。因此,規則應在啟動階段新增。將模組的 URL 規則包裝在 yii\web\GroupUrlRule 中也是一個好習慣。
如果模組用於版本化 API,則其 URL 規則應直接新增到應用程式配置的 urlManager
區段中。
在模組中,您可能經常需要取得模組類別的實例,以便您可以存取模組 ID、模組參數、模組組件等。您可以使用以下語句來執行此操作
$module = MyModuleClass::getInstance();
其中 MyModuleClass
指的是您感興趣的模組類別的名稱。 getInstance()
方法將傳回目前請求的模組類別的實例。如果未請求模組,則該方法將傳回 null
。請注意,您不想手動建立模組類別的新實例,因為它將與 Yii 響應請求而建立的實例不同。
資訊:在開發模組時,您不應假設模組將使用固定的 ID。這是因為當在應用程式中或另一個模組中使用模組時,模組可以與任意 ID 關聯。為了取得模組 ID,您應該使用上述方法首先取得模組實例,然後透過
$module->id
取得 ID。
您也可以使用以下方法存取模組的實例
// get the child module whose ID is "forum"
$module = \Yii::$app->getModule('forum');
// get the module to which the currently requested controller belongs
$module = \Yii::$app->controller->module;
第一種方法僅在您知道模組 ID 時才有用,而第二種方法最適合在您了解正在請求的控制器時使用。
一旦您擁有模組實例,您就可以存取向模組註冊的參數和組件。例如,
$maxPostCount = $module->params['maxPostCount'];
某些模組可能需要在每個請求中執行。yii\debug\Module 模組就是這樣一個範例。為此,請在應用程式的 bootstrap 屬性中列出此類模組的 ID。
例如,以下應用程式配置確保始終載入 debug
模組
[
'bootstrap' => [
'debug',
],
'modules' => [
'debug' => 'yii\debug\Module',
],
]
模組可以巢狀在無限層級中。也就是說,一個模組可以包含另一個模組,而該模組又可以包含另一個模組。我們將前者稱為父模組,而將後者稱為子模組。子模組必須在其父模組的 modules 屬性中宣告。例如,
namespace app\modules\forum;
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
$this->modules = [
'admin' => [
// you should consider using a shorter namespace here!
'class' => 'app\modules\forum\modules\admin\Module',
],
];
}
}
對於巢狀模組中的控制器,其路由應包含其所有祖先模組的 ID。例如,路由 forum/admin/dashboard/index
表示 admin
模組中 dashboard
控制器的 index
操作,該模組是 forum
模組的子模組。
資訊:getModule() 方法僅傳回直接屬於其父模組的子模組。yii\base\Application::$loadedModules 屬性保留已載入模組的清單,包括直接子模組和巢狀子模組,並按其類別名稱索引。
自 2.0.13 版本起,模組支援樹狀遍歷。這允許模組開發人員透過作為其模組的服務定位器來引用(應用程式)組件。這表示最好使用 $module->get('db')
而不是 Yii::$app->get('db')
。如果需要不同的組件(配置),模組的使用者可以指定要用於模組的特定組件。
例如,考慮以下部分應用程式配置
'components' => [
'db' => [
'tablePrefix' => 'main_',
'class' => Connection::class,
'enableQueryCache' => false
],
],
'modules' => [
'mymodule' => [
'components' => [
'db' => [
'tablePrefix' => 'module_',
'class' => Connection::class
],
],
],
],
應用程式資料庫表將以 main_
為前綴,而所有模組表將以 module_
為前綴。請注意,上面的配置未合併;例如,模組的組件將啟用查詢快取,因為那是預設值。
模組最適合用於大型應用程式,這些應用程式的功能可以分為幾個組,每個組由一組密切相關的功能組成。每個這樣的功能組都可以開發為模組,由特定的開發人員或團隊開發和維護。
模組也是在功能組層級重用程式碼的好方法。一些常用的功能,例如使用者管理、評論管理,都可以以模組的形式開發,以便可以在未來的專案中輕鬆重用。
發現錯字或您認為此頁面需要改進?
在 github 上編輯它 !
如果您嘗試在自己的自訂模組的 Bootstrap 類別或模組的規則類別中取得它,則始終會在您自己的模組內傳回 null。
程式碼不正確,
$this
->\Yii::$app
變更之前
public function init() { parent::init(); // initialize the module with the configuration loaded from config.php \Yii::configure($this, require __DIR__ . '/config.php'); }
修改後
public function init() { parent::init(); // initialize the module with the configuration loaded from config.php \Yii::configure(\Yii::$app, require __DIR__ . '/config.php'); }
最後,我的
config.php
<?php return [ 'components' => [ 'response' => [ 'class' => 'yii\web\Response', 'format' => \yii\web\Response::FORMAT_JSON, 'charset' => 'UTF-8', ], ], 'params' => [ // list of parameters ], ];
此頁面中顯示的程式碼是正確的,因為它正在初始化模組物件,而不是應用程式物件。
\Yii::configure($this, require __DIR__ . '/config.php');
註冊 或 登入 以發表評論。