extend-creating-extensions.md 7.12 KB
Newer Older
1 2
Extending Yii
=============
Qiang Xue committed
3

4
> Note: This section is under development.
Qiang Xue committed
5

6
The Yii framework was designed to be easily extendable. Additional features can be added to your project and then reused, either by yourself on other projects or by sharing your work as a formal Yii extension.
7

8 9 10
Code style
----------

11 12 13 14 15 16
To be consistent with core Yii conventions, your extensions ought to adhere to certain coding styles:

- Use the [core framework code style](https://github.com/yiisoft/yii2/wiki/Core-framework-code-style).
- Document classes, methods and properties using [phpdoc](http://www.phpdoc.org/). - Extension classes should *not* be prefixed. Do not use the format `TbNavBar`, `EMyWidget`, etc.

> Note that you can use Markdown within your code for documentation purposes. With Markdown, you can link to properties and methods using the following syntax: `[[name()]]`, `[[namespace\MyClass::name()]]`.
17

18
### Namespace
19

20 21 22 23 24
Yii 2 relies upon namespaces to organize code. (Namespace support was added to PHP in version 5.3.) If you want to use namespaces within your extension,

- Do not use `yiisoft` anywhere in your namespaces.
- Do not use `\yii`, `\yii2` or `\yiisoft` as root namespaces.
- Namespaces should use the syntax `vendorName\uniqueName`.
25

26
Choosing a unique namespace is important to prevent name collisions, and also results in faster autoloading of classes. Examples of unique, consistent namepacing are:
27 28

- `samdark\wiki`
29 30
- `samdark\debugger`
- `samdark\googlemap`
31 32 33 34

Distribution
------------

35 36 37 38 39 40 41 42
Beyond the code itself, the entire extension distribution ought to have certain things.

There should be a `readme.md` file, written in English. This file should clearly describe what the extension does, its requirements, how to install it, 
  and to use it. The README should be written using Markdown. If you want to provide translated README files, name them as `readme_ru.md`
  where `ru` is your language code (in this case, Russian). 
  
  It is a good idea to include some screenshots as part of the documentation, especially if your extension provides a widget. 
  
43
It is recommended to host your extensions at [Github](https://github.com).
44 45

Extensions should also be registered at [Packagist](https://packagist.org) in order to be installable via Composer. 
46 47 48

### Composer package name

49 50
Choose your extension's package name wisely, as you shouldn't change the package name later on. (Changing the name leads to losing the Composer stats, and makes it impossible for people  to install the package by the old name.) 

51 52 53 54 55 56 57
If your extension was made specifically for Yii2 (i.e. cannot be used as a standalone PHP library) it is recommended to
name it like the following:

```
yii2-my-extension-name-type
```

58
Where: 
59

60 61 62
- `yii2-` is a prefix.
- The extension name is in all lowercase letters, with words separated by `-`.
- The `-type` postfix may be `widget`, `behavior`, `module` etc.
63

64 65
### Dependencies

66 67 68
Some extensions you develop may have their own dependencies, such as relying upon other extensions or third-party libraries. When dependencies exist, you should require them in your extension's `composer.json` file. Be certain to also use appropriate version constraints, eg. `1.*`, `@stable` for requirements.

Finally, when your extension is released in a stable version, double-check that its requirements do not include `dev` packages that do not have a `stable` release. In other words, the stable release of your extension should only rely upon stable dependencies.
69 70 71

### Versioning

72 73
As you maintain and upgrading your extension, 

74 75 76
- Use the rules of [semantic versioning](http://semver.org).
- Use a consistent format for your repository tags, as they are treated as version strings by composer, eg. `0.2.4`,
  `0.2.5`,`0.3.0`,`1.0.0`.
77

78 79
### composer.json

80 81
Yii2 uses Composer for installation, and extensions for Yii2 should as well. Towards that end, 

82
- Use the type `yii2-extension` in `composer.json` file if your extension is Yii-specific.
83 84
- Do not use `yii` or `yii2` as the Composer vendor name.
- Do not use `yiisoft` in the Composer package name or the Composer vendor name.
85

86
If your extension classes reside directly in the repository root directory, you can use the PSR-4 autoloader in the following way in your `composer.json` file:
87

88
```json
89
{
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
    "name": "myname/mywidget",
    "description": "My widget is a cool widget that does everything",
    "keywords": ["yii", "extension", "widget", "cool"],
    "homepage": "https://github.com/myname/yii2-mywidget-widget",
    "type": "yii2-extension",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "John Doe",
            "email": "doe@example.com"
        }
    ],
    "require": {
        "yiisoft/yii2": "*"
    },
    "autoload": {
        "psr-4": {
            "myname\\mywidget\\": ""
108
        }
109
    }
110 111 112
}
```

113 114
In the above, `myname/mywidget` is the package name that will be registered
at [Packagist](https://packagist.org). It is common for the package name to match your Github repository name.
115
Also, the `psr-4` autoloader is specified in the above, which maps the `myname\mywidget` namespace to the root directory where the classes reside.
116

117
More details on this syntax can be found in the [Composer documentation](http://getcomposer.org/doc/04-schema.md#autoload).
118

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

### Bootstrap with extension

Sometimes, you may want your extension to execute some code during the bootstrap stage of an application.
For example, your extension may want to respond to the application's `beginRequest` event. You can ask the extension user
to explicitly attach your event handler in the extension to the application's event. A better way, however, is to
do all these automatically.

To achieve this goal, you can create a bootstrap class by implementing [[yii\base\BootstrapInterface]].

```php
namespace myname\mywidget;

use yii\base\BootstrapInterface;
use yii\base\Application;

135
class MyBootstrapClass implements BootstrapInterface
136
{
137
    public function bootstrap($app)
138 139 140 141 142 143 144 145 146 147 148 149 150
    {
        $app->on(Application::EVENT_BEFORE_REQUEST, function () {
             // do something here
        });
    }
}
```

You then list this bootstrap class in `composer.json` as follows,

```json
{
    "extra": {
151
        "bootstrap": "myname\\mywidget\\MyBootstrapClass"
152 153 154 155
    }
}
```

Qiang Xue committed
156 157 158
When the extension is installed in an application, Yii will automatically hook up the bootstrap class
and call its `bootstrap()` while initializing the application for every request.

159

160 161 162
Working with database
---------------------

163
Extensions sometimes have to use their own database tables. In such a situation,
164 165

- If the extension creates or modifies the database schema, always use Yii migrations instead of SQL files or custom scripts.
166
- Migrations should be applicable to different database systems.
167
- Do not use Active Record models in your migrations.
168 169 170 171

Assets
------

172
- Register assets [through bundles](assets.md).
173 174 175 176

Events
------

Tobias Munk committed
177
TBD
178 179 180 181

i18n
----

182 183 184
- If extension outputs messages intended for end user these should be wrapped into `Yii::t()` in order to be translatable.
- Exceptions and other developer-oriented message should not be translated.
- Consider proving `config.php` for `yii message` command to simplify translation.
185 186 187 188

Testing your extension
----------------------

189
- Consider adding unit tests for PHPUnit.