Commit 1005b32b by funson86

for check

parent 49cb7a6a
模块
Modules Modules
======= =======
Modules are self-contained software units that consist of [models](structure-models.md), [views](structure-views.md), 模块是独立的软件单元,由[模型](structure-models.md), [视图](structure-views.md),
[controllers](structure-controllers.md), and other supporting components. End users can access the controllers [控制器](structure-controllers.md)和其他支持组件组成,
of a module when it is installed in [application](structure-applications.md). For these reasons, modules are 终端用户可以访问在[应用主体](structure-applications.md)中已安装的模块的控制器,
often viewed as mini-applications. Modules differ from [applications](structure-applications.md) in that 模块被当成小应用主体来看待,和[应用主体](structure-applications.md)不同的是,
modules cannot be deployed alone and must reside within applications. 模块不能单独部署,必须属于某个应用主体。
## 创建模块 <a name="creating-modules"></a>
## Creating Modules <a name="creating-modules"></a> ## Creating Modules <a name="creating-modules"></a>
A module is organized as a directory which is called the [[yii\base\Module::basePath|base path]] of the module. 模块被组织成一个称为[[yii\base\Module::basePath|base path]]的目录,
Within the directory, there are sub-directories, such as `controllers`, `models`, `views`, which hold controllers, 在该目录中有子目录如`controllers`, `models`, `views` 分别为对应控制器,模型,视图和其他代码,和应用非常类似。
models, views, and other code, just like in an application. The following example shows the content within a module: 如下例子显示一个模型的目录结构:
``` ```
forum/ forum/
Module.php the module class file Module.php 模块类文件
controllers/ containing controller class files controllers/ 包含控制器类文件
DefaultController.php the default controller class file DefaultController.php default 控制器类文件
models/ containing model class files models/ 包含模型类文件
views/ containing controller view and layout files views/ 包含控制器视图文件和布局文件
layouts/ containing layout view files layouts/ 包含布局文件
default/ containing view files for DefaultController default/ 包含DefaultController控制器视图文件
index.php the index view file index.php index视图文件
``` ```
### 模块类 <a name="module-classes"></a>
### Module Classes <a name="module-classes"></a> ### Module Classes <a name="module-classes"></a>
每个模块都有一个继承[[yii\base\Module]]的模块类,该类文件直接放在模块的[[yii\base\Module::basePath|base path]]目录下,
并且能被 [自动加载](concept-autoloading.md)。当一个模块被访问,和 [application instances](structure-applications.md)
类似会创建该模块类唯一实例,模块实例用来帮模块内代码共享数据和组件。
Each module should have a module class which extends from [[yii\base\Module]]. The class should be located Each module should have a module class which extends from [[yii\base\Module]]. The class should be located
directly under the module's [[yii\base\Module::basePath|base path]] and should be [autoloadable](concept-autoloading.md). directly under the module's [[yii\base\Module::basePath|base path]] and should be [autoloadable](concept-autoloading.md).
When a module is being accessed, a single instance of the corresponding module class will be created. When a module is being accessed, a single instance of the corresponding module class will be created.
Like [application instances](structure-applications.md), module instances are used to share data and components Like [application instances](structure-applications.md), module instances are used to share data and components
for code within modules. for code within modules.
以下示例一个模块类大致定义:
The following is an example how a module class may look like: The following is an example how a module class may look like:
```php ```php
...@@ -47,11 +54,13 @@ class Module extends \yii\base\Module ...@@ -47,11 +54,13 @@ class Module extends \yii\base\Module
parent::init(); parent::init();
$this->params['foo'] = 'bar'; $this->params['foo'] = 'bar';
// ... other initialization code ... // ... 其他初始化代码 ...
} }
} }
``` ```
如果 `init()` 方法包含很多初始化模块属性代码,
可将他们保存在[配置](concept-configurations.md) 并在`init()`中使用以下代码加载:
If the `init()` method contains a lot of code initializing the module's properties, you may also save them in terms If the `init()` method contains a lot of code initializing the module's properties, you may also save them in terms
of a [configuration](concept-configurations.md) and load it with the following code in `init()`: of a [configuration](concept-configurations.md) and load it with the following code in `init()`:
...@@ -59,11 +68,12 @@ of a [configuration](concept-configurations.md) and load it with the following c ...@@ -59,11 +68,12 @@ of a [configuration](concept-configurations.md) and load it with the following c
public function init() public function init()
{ {
parent::init(); parent::init();
// initialize the module with the configuration loaded from config.php // 从config.php加载配置来初始化模块
\Yii::configure($this, require(__DIR__ . '/config.php')); \Yii::configure($this, require(__DIR__ . '/config.php'));
} }
``` ```
`config.php`配置文件可能包含以下内容,类似[应用主体配置](structure-applications.md#application-configurations).
where the configuration file `config.php` may contain the following content, similar to that in an where the configuration file `config.php` may contain the following content, similar to that in an
[application configuration](structure-applications.md#application-configurations). [application configuration](structure-applications.md#application-configurations).
...@@ -80,13 +90,12 @@ return [ ...@@ -80,13 +90,12 @@ return [
``` ```
### 模块中的控制器 <a name="controllers-in-modules"></a>
### Controllers in Modules <a name="controllers-in-modules"></a> ### Controllers in Modules <a name="controllers-in-modules"></a>
When creating controllers in a module, a convention is to put the controller classes under the `controllers` 创建模块的控制器时,惯例是将控制器类放在模块类命名空间的`controllers`子命名空间中,
sub-namespace of the namespace of the module class. This also means the controller class files should be 也意味着要将控制器类文件放在模块[[yii\base\Module::basePath|base path]]目录中的`controllers`子目录中。
put in the `controllers` directory within the module's [[yii\base\Module::basePath|base path]]. 例如,上小节中要在`forum`模块中创建`post`控制器,应像如下申明控制器类:
For example, to create a `post` controller in the `forum` module shown in the last subsection, you should
declare the controller class like the following:
```php ```php
namespace app\modules\forum\controllers; namespace app\modules\forum\controllers;
...@@ -99,27 +108,36 @@ class PostController extends Controller ...@@ -99,27 +108,36 @@ class PostController extends Controller
} }
``` ```
可配置[[yii\base\Module::controllerNamespace]]属性来自定义控制器类的命名空间,
如果一些控制器不再该命名空间下,可配置[[yii\base\Module::controllerMap]]属性让它们能被访问,
这类似于 [应用主体配置](structure-applications.md#controller-map) 所做的。
You may customize the namespace of controller classes by configuring the [[yii\base\Module::controllerNamespace]] You may customize the namespace of controller classes by configuring the [[yii\base\Module::controllerNamespace]]
property. In case when some of the controllers are out of this namespace, you may make them accessible property. In case when some of the controllers are out of this namespace, you may make them accessible
by configuring the [[yii\base\Module::controllerMap]] property, similar to [what you do in an application](structure-applications.md#controller-map). by configuring the [[yii\base\Module::controllerMap]] property, similar to [what you do in an application](structure-applications.md#controller-map).
### 模块中的视图 <a name="views-in-modules"></a>
### Views in Modules <a name="views-in-modules"></a> ### Views in Modules <a name="views-in-modules"></a>
Views in a module should be put in the `views` directory within the module's [[yii\base\Module::basePath|base path]]. 视图应放在模块的[[yii\base\Module::basePath|base path]]对应目录下的 `views` 目录,
For views rendered by a controller in the module, they should be put under the directory `views/ControllerID`, 对于模块中控制器对应的视图文件应放在 `views/ControllerID` 目录下,
where `ControllerID` refers to the [controller ID](structure-controllers.md#routes). For example, if 其中`ControllerID`对应 [控制器 ID](structure-controllers.md#routes). For example, if
the controller class is `PostController`, the directory would be `views/post` within the module's 例如,假定控制器类为`PostController`,目录对应模块[[yii\base\Module::basePath|base path]]目录下的 `views/post` 目录。
[[yii\base\Module::basePath|base path]].
模块可指定 [布局](structure-views.md#layouts),它用在模块的控制器视图渲染。
布局文件默认放在 `views/layouts` 目录下,可配置[[yii\base\Module::layout]]属性指定布局名,
如果没有配置 `layout` 属性名,默认会使用应用的布局。
A module can specify a [layout](structure-views.md#layouts) that is applied to the views rendered by the module's A module can specify a [layout](structure-views.md#layouts) that is applied to the views rendered by the module's
controllers. The layout should be put in the `views/layouts` directory by default, and you should configure controllers. The layout should be put in the `views/layouts` directory by default, and you should configure
the [[yii\base\Module::layout]] property to point to the layout name. If you do not configure the `layout` property, the [[yii\base\Module::layout]] property to point to the layout name. If you do not configure the `layout` property,
the application's layout will be used instead. the application's layout will be used instead.
## 使用模块 <a name="using-modules"></a>
## Using Modules <a name="using-modules"></a> ## Using Modules <a name="using-modules"></a>
要在应用中使用模块,只需要将模块加入到应用主体配置的[[yii\base\Application::modules|modules]]属性的列表中,
如下代码的[应用主体配置](structure-applications.md#application-configurations) 使用 `forum` 模块:
To use a module in an application, simply configure the application by listing the module in To use a module in an application, simply configure the application by listing the module in
the [[yii\base\Application::modules|modules]] property of the application. The following code in the the [[yii\base\Application::modules|modules]] property of the application. The following code in the
[application configuration](structure-applications.md#application-configurations) uses the `forum` module: [application configuration](structure-applications.md#application-configurations) uses the `forum` module:
...@@ -129,19 +147,27 @@ the [[yii\base\Application::modules|modules]] property of the application. The f ...@@ -129,19 +147,27 @@ the [[yii\base\Application::modules|modules]] property of the application. The f
'modules' => [ 'modules' => [
'forum' => [ 'forum' => [
'class' => 'app\modules\forum\Module', 'class' => 'app\modules\forum\Module',
// ... other configurations for the module ... // ... 模块其他配置 ...
], ],
], ],
] ]
``` ```
[[yii\base\Application::modules|modules]] 属性使用模块配置数组,每个数组键为*模块 ID*
它标识该应用中唯一的模块,数组的值为用来创建模块的 [配置](concept-configurations.md)
The [[yii\base\Application::modules|modules]] property takes an array of module configurations. Each array key The [[yii\base\Application::modules|modules]] property takes an array of module configurations. Each array key
represents a *module ID* which uniquely identifies the module among all modules in the application, and the corresponding represents a *module ID* which uniquely identifies the module among all modules in the application, and the corresponding
array value is a [configuration](concept-configurations.md) for creating the module. array value is a [configuration](concept-configurations.md) for creating the module.
### 路由 <a name="routes"></a>
### Routes <a name="routes"></a> ### Routes <a name="routes"></a>
和访问应用的控制器类似,[路由](structure-controllers.md#routes) 也用在模块中控制器的寻址,
模块中控制器的路由必须以模块ID开始,接下来为控制器ID和操作ID。
例如,假定应用使用一个名为 `forum` 模块,路由`forum/post/index` 代表模块中 `post` 控制器的 `index` 操作,
如果路由只包含模块ID,默认为 `default`[[yii\base\Module::defaultRoute]] 属性来决定使用哪个控制器/操作,
也就是说路由 `forum` 可能代表 `forum` 模块的 `default` 控制器。
Like accessing controllers in an application, [routes](structure-controllers.md#routes) are used to address Like accessing controllers in an application, [routes](structure-controllers.md#routes) are used to address
controllers in a module. A route for a controller within a module must begin with the module ID followed by controllers in a module. A route for a controller within a module must begin with the module ID followed by
the controller ID and action ID. For example, if an application uses a module named `forum`, then the route the controller ID and action ID. For example, if an application uses a module named `forum`, then the route
...@@ -151,8 +177,11 @@ will determine which controller/action should be used. This means a route `forum ...@@ -151,8 +177,11 @@ will determine which controller/action should be used. This means a route `forum
controller in the `forum` module. controller in the `forum` module.
### 访问模块 <a name="accessing-modules"></a>
### Accessing Modules <a name="accessing-modules"></a> ### Accessing Modules <a name="accessing-modules"></a>
在模块中,可能经常需要获取[模块类](#module-classes)的实例来访问模块ID,模块参数,模块组件等,
可以使用如下语句来获取:
Within a module, you may often need to get the instance of the [module class](#module-classes) so that you can Within a module, you may often need to get the instance of the [module class](#module-classes) so that you can
access the module ID, module parameters, module components, etc. You can do so by using the following statement: access the module ID, module parameters, module components, etc. You can do so by using the following statement:
...@@ -160,29 +189,32 @@ access the module ID, module parameters, module components, etc. You can do so b ...@@ -160,29 +189,32 @@ access the module ID, module parameters, module components, etc. You can do so b
$module = MyModuleClass::getInstance(); $module = MyModuleClass::getInstance();
``` ```
where `MyModuleClass` refers to the name of the module class that you are interested in. The `getInstance()` method 其中 `MyModuleClass` 对应你想要的模块类,`getInstance()` 方法返回当前请求的模块类实例,
will return the currently requested instance of the module class. If the module is not requested, the method will 如果模块没有被请求,该方法会返回空,注意不需要手动创建一个模块类,因为手动创建的和Yii处理请求时自动创建的不同。
return null. Note that You do not want to manually create a new instance of the module class because it will be
different from the one created by Yii in response to a request.
> 补充: 当开发模块时,你不能假定模块使用固定的ID,因为在应用或其他没模块中,模块可能会对应到任意的ID,
为了获取模块ID,应使用上述代码获取模块实例,然后通过`$module->id`获取模块ID。
> Info: When developing a module, you should not assume the module will use a fixed ID. This is because a module > Info: When developing a module, you should not assume the module will use a fixed ID. This is because a module
can be associated with an arbitrary ID when used in an application or within another module. In order to get can be associated with an arbitrary ID when used in an application or within another module. In order to get
the module ID, you should use the above approach to get the module instance first, and then get the ID via the module ID, you should use the above approach to get the module instance first, and then get the ID via
`$module->id`. `$module->id`.
也可以使用如下方式访问模块实例:
You may also access the instance of a module using the following approaches: You may also access the instance of a module using the following approaches:
```php ```php
// get the module whose ID is "forum" // 获取ID为 "forum" 的模块
$module = \Yii::$app->getModule('forum'); $module = \Yii::$app->getModule('forum');
// get the module to which the currently requested controller belongs // 获取处理当前请求控制器所属的模块
$module = \Yii::$app->controller->module; $module = \Yii::$app->controller->module;
``` ```
第一种方式仅在你知道模块ID的情况下有效,第二种方式在你知道处理请求的控制器下使用。
The first approach is only useful when you know the module ID, while the second approach is best used when you The first approach is only useful when you know the module ID, while the second approach is best used when you
know about the controllers being requested. know about the controllers being requested.
一旦获取到模块实例,可访问注册到模块的参数和组件,例如:
Once getting hold of a module instance, you can access parameters or components registered with the module. For example, Once getting hold of a module instance, you can access parameters or components registered with the module. For example,
```php ```php
...@@ -190,11 +222,15 @@ $maxPostCount = $module->params['maxPostCount']; ...@@ -190,11 +222,15 @@ $maxPostCount = $module->params['maxPostCount'];
``` ```
### 引导启动模块 <a name="bootstrapping-modules"></a>
### Bootstrapping Modules <a name="bootstrapping-modules"></a> ### Bootstrapping Modules <a name="bootstrapping-modules"></a>
有些模块在每个请求下都有运行, [[yii\debug\Module|debug]] 模块就是这种,
为此将这种模块加入到应用主体的 [[yii\base\Application::bootstrap|bootstrap]] 属性中。
Some modules may need to be run for every request. The [[yii\debug\Module|debug]] module is such an example. Some modules may need to be run for every request. The [[yii\debug\Module|debug]] module is such an example.
To do so, list the IDs of such modules in the [[yii\base\Application::bootstrap|bootstrap]] property of the application. To do so, list the IDs of such modules in the [[yii\base\Application::bootstrap|bootstrap]] property of the application.
例如,如下示例的应用主体配置会确保`debug`模块每次都被加载:
For example, the following application configuration makes sure the `debug` module is always load: For example, the following application configuration makes sure the `debug` module is always load:
```php ```php
...@@ -210,11 +246,11 @@ For example, the following application configuration makes sure the `debug` modu ...@@ -210,11 +246,11 @@ For example, the following application configuration makes sure the `debug` modu
``` ```
## 模块嵌套 <a name="nested-modules"></a>
## Nested Modules <a name="nested-modules"></a> ## Nested Modules <a name="nested-modules"></a>
Modules can be nested in unlimited levels. That is, a module can contain another module which can contain yet 模块可无限级嵌套,也就是说,模块可以包含另一个包含模块的模块,我们称前者为*父模块*,后者为*子模块*
another module. We call the former *parent module* while the latter *child module*. Child modules must be declared 子模块必须在父模块的[[yii\base\Module::modules|modules]]属性中申明,例如:
in the [[yii\base\Module::modules|modules]] property of their parent modules. For example,
```php ```php
namespace app\modules\forum; namespace app\modules\forum;
...@@ -227,7 +263,7 @@ class Module extends \yii\base\Module ...@@ -227,7 +263,7 @@ class Module extends \yii\base\Module
$this->modules = [ $this->modules = [
'admin' => [ 'admin' => [
// you should consider using a shorter namespace here! // 此处应考虑使用一个更短的命名空间
'class' => 'app\modules\forum\modules\admin\Module', 'class' => 'app\modules\forum\modules\admin\Module',
], ],
]; ];
...@@ -235,17 +271,21 @@ class Module extends \yii\base\Module ...@@ -235,17 +271,21 @@ class Module extends \yii\base\Module
} }
``` ```
For a controller within a nested module, its route should include the IDs of all its ancestor module. 在嵌套模块中的控制器,它的路由应包含它所有祖先模块的ID,例如`forum/admin/dashboard/index` 代表
For example, the route `forum/admin/dashboard/index` represents the `index` action of the `dashboard` controller 在模块`forum`中子模块`admin``dashboard`控制器的`index`操作。
in the `admin` module which is a child module of the `forum` module.
## 最佳实践 <a name="best-practices"></a>
## Best Practices <a name="best-practices"></a> ## Best Practices <a name="best-practices"></a>
模块在大型项目中常备使用,这些项目的特性可分组,每个组包含一些强相关的特性,
每个特性组可以做成一个模块由特定的开发人员和开发组来开发和维护。
Modules are best used in large applications whose features can be divided into several groups, each consisting of Modules are best used in large applications whose features can be divided into several groups, each consisting of
a set of closely related features. Each such feature group can be developed as a module which is developed and a set of closely related features. Each such feature group can be developed as a module which is developed and
maintained by a specific developer or team. maintained by a specific developer or team.
在特性组上,使用模块也是重用代码的好方式,一些常用特性,如用户管理,评论管理,可以开发成模块,
这样在相关项目中非常容易被重用。
Modules are also a good way of reusing code at the feature group level. Some commonly used features, such as Modules are also a good way of reusing code at the feature group level. Some commonly used features, such as
user management, comment management, can all be developed in terms of modules so that they can be reused easily user management, comment management, can all be developed in terms of modules so that they can be reused easily
in future projects. in future projects.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment