structure-modules.md 9.15 KB
Newer Older
Qiang Xue committed
1 2 3 4 5 6 7 8 9
Modules
=======

Modules are self-contained software units that consist of [models](structure-models.md), [views](structure-views.md),
[controllers](structure-controllers.md), and other supporting components. End users can access the controllers
of a module when it is installed in [application](structure-applications.md). Modules differ from
[applications](structure-applications.md) in that the former cannot be deployed alone and must reside within the latter.


10
## Creating Modules <a name="creating-modules"></a>
Qiang Xue committed
11 12

A module is organized as a directory which is called the [[yii\base\Module::basePath|base path]] of the module.
13 14
Within the directory, there are sub-directories, such as `controllers`, `models`, `views`, which hold controllers,
models, views, and other code, just like in an application. The following example shows the content within a module:
Qiang Xue committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28

```
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
```


29
### Module Classes <a name="module-classes"></a>
Qiang Xue committed
30

31 32 33 34
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).
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
Qiang Xue committed
35 36
for code within modules.

37
The following is an example how a module class may look like:
Qiang Xue committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

```php
namespace app\modules\forum;

class Module extends \yii\base\Module
{
    public function init()
    {
        parent::init();

        $this->params['foo'] = 'bar';
        // ...  other initialization code ...
    }
}
```

54
If the `init()` method contains a lot of code initializing the module's properties, you may also save them in terms
Qiang Xue committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
of a [configuration](concept-configurations.md) and load it with the following code in `init()`:

```php
public function init()
{
    parent::init();
    // initialize the module with the configuration loaded from config.php
    \Yii::configure($this, require(__DIR__ . '/config.php'));
}
```

where the configuration file `config.php` may contain the following content, similar to that in an
[application configuration](structure-applications.md#application-configurations).

```php
<?php
return [
    'components' => [
        // list of component configurations
    ],
    'params' => [
        // list of parameters
    ],
];
```

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

### 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`
sub-namespace of the namespace of the module class. This also means the controller class files should be
put in the `controllers` directory within the module's [[yii\base\Module::basePath|base path]].
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
namespace app\modules\forum\controllers;

use yii\web\Controller;

class PostController extends Controller
{
    // ...
}
```

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
by configuring the [[yii\base\Module::controllerMap]] property, similar to [what you do in an application](structure-applications.md#controller-map).


### 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]].
For views rendered by a controller in the module, they should be put under the directory `views/ControllerID`,
where `ControllerID` refers to the [controller ID](structure-controllers.md#routes). For example, if
the controller class is `PostController`, the directory would be `views/post` within the module's
[[yii\base\Module::basePath|base path]].

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
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.


## Using Modules <a name="using-modules"></a>

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
[application configuration](structure-applications.md#application-configurations) uses the `forum` module:

```php
[
    'modules' => [
        'forum' => [
            'class' => 'app\modules\forum\Module',
            // ... other configurations for the module ...
        ],
    ],
]
```

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
array value is a [configuration](concept-configurations.md) for creating the module.
Qiang Xue committed
140 141


142
### Routes <a name="routes"></a>
Qiang Xue committed
143

144 145 146 147 148 149 150
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
the controller ID and action ID. For example, if an application uses a module named `forum`, then the route
`forum/post/index` would represent the `index` action of the `post` controller in the module. If the route
only contains the module ID, then the [[yii\base\Module::defaultRoute]] property, which defaults to `default`,
will determine which controller/action should be used. This means a route `forum` would represent the `default`
controller in the `forum` module.
Qiang Xue committed
151 152


153
### Accessing Modules <a name="accessing-modules"></a>
Qiang Xue committed
154

155 156
A module is instantiated when one of its controllers is accessed by end users. You may access the instance of a module
using the approaches shown in the following example:
Qiang Xue committed
157

158 159 160
```php
// get the module whose ID is "forum"
$module = \Yii::$app->getModule('forum');
Qiang Xue committed
161

162 163 164
// get the module to which the currently requested controller belongs
$module = \Yii::$app->controller->module;
```
Qiang Xue committed
165

166 167
The first approach is only useful in application code which has knowledge about the module ID, while the second approach
is best used by the code within the module.
Qiang Xue committed
168

169
Once getting hold of a module instance, you can access parameters or components registered with the module. For example,
Qiang Xue committed
170

171 172 173
```php
$maxPostCount = $module->params['maxPostCount'];
```
Qiang Xue committed
174 175


176
### Bootstrapping Modules <a name="bootstrapping-modules"></a>
Qiang Xue committed
177

178 179
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.
Qiang Xue committed
180

181 182 183 184 185 186 187 188 189 190 191 192 193
For example, the following application configuration makes sure the `debug` module is always load:

```php
[
    'bootstrap' => [
        'debug',
    ],

    'modules' => [
        'debug' => 'yii\debug\Module',
    ],
]
```
Qiang Xue committed
194 195


196
## Nested Modules <a name="nested-modules"></a>
Qiang Xue committed
197

198 199 200
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
in the [[yii\bas\Module::modules|modules]] property of their parent modules. For example,
Qiang Xue committed
201

202 203
```php
namespace app\modules\forum;
Qiang Xue committed
204

205 206 207 208 209
class Module extends \yii\base\Module
{
    public function init()
    {
        parent::init();
Qiang Xue committed
210

211 212 213 214 215 216 217 218 219
        $this->modules = [
            'admin' => [
                // you should consider using a shorter namespace here!
                'class' => 'app\modules\forum\modules\admin\Module',
            ],
        ];
    }
}
```
Qiang Xue committed
220

221 222 223
For a controller within a nested module, its route should include the IDs of all its ancestor module.
For example, the route `forum/admin/dashboard/index` represents the `index` action of the `dashboard` controller
in the `admin` module which is a child module of the `forum` module.
Qiang Xue committed
224 225


226
## Best Practices <a name="best-practices"></a>
Qiang Xue committed
227

228 229 230
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
maintained by a specific developer or team.
Qiang Xue committed
231

232 233 234
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 resued easily
in future projects.