Commit b9eb5de9 by Qiang Xue

Fixes #2796: Added BootstrapInterface.

parent 7c91af53
...@@ -82,7 +82,7 @@ Yii2 uses Composer for installation, and extensions for Yii2 should as well. Tow ...@@ -82,7 +82,7 @@ Yii2 uses Composer for installation, and extensions for Yii2 should as well. Tow
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: 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:
``` ```json
{ {
"name": "myname/mywidget", "name": "myname/mywidget",
"description": "My widget is a cool widget that does everything", "description": "My widget is a cool widget that does everything",
...@@ -109,18 +109,55 @@ If your extension classes reside directly in the repository root directory, you ...@@ -109,18 +109,55 @@ If your extension classes reside directly in the repository root directory, you
In the above, `myname/mywidget` is the package name that will be registered 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. at [Packagist](https://packagist.org). It is common for the package name to match your Github repository name.
Also, the `psr-4` autoloader is specified in the above, which maps the `myname\mywidget` namespace to the root directory where the classes reside.
In the above, the `psr-4` autoloader is specified, mapping the `myname\mywidget` namespace to the root directory where the classes reside.
More details on this syntax can be found in the [Composer documentation](http://getcomposer.org/doc/04-schema.md#autoload). More details on this syntax can be found in the [Composer documentation](http://getcomposer.org/doc/04-schema.md#autoload).
### 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;
class Bootstrap implements BootstrapInterface
{
public function bootstrap(Application $app)
{
$app->on(Application::EVENT_BEFORE_REQUEST, function () {
// do something here
});
}
}
```
You then list this bootstrap class in `composer.json` as follows,
```json
{
"extra": {
"bootstrap": "path\\to\\MyBootstrapClass"
}
}
```
Working with database Working with database
--------------------- ---------------------
Extensions sometimes have to use their own database tables. In such situations, Extensions sometimes have to use their own database tables. In such a situation,
- If the extension creates or modifies the database schema, always use Yii migrations instead of SQL files or custom scripts. - If the extension creates or modifies the database schema, always use Yii migrations instead of SQL files or custom scripts.
- Migrations should be applicable to as many data storages as possible. - Migrations should be applicable to different database systems.
- Do not use Active Record models in your migrations. - Do not use Active Record models in your migrations.
Assets Assets
......
...@@ -151,7 +151,7 @@ Yii Framework 2 Change Log ...@@ -151,7 +151,7 @@ Yii Framework 2 Change Log
- Enh #2729: Added `FilterValidator::skipOnArray` so that filters like `trim` will not fail for array inputs (qiangxue) - Enh #2729: Added `FilterValidator::skipOnArray` so that filters like `trim` will not fail for array inputs (qiangxue)
- Enh #2735: Added support for `DateTimeInterface` in `Formatter` (ivokund) - Enh #2735: Added support for `DateTimeInterface` in `Formatter` (ivokund)
- Enh #2756: Added support for injecting custom `isEmpty` check for all validators (qiangxue) - Enh #2756: Added support for injecting custom `isEmpty` check for all validators (qiangxue)
- Enh #2775: Added `yii\base\Application::bootstrap` to support running bootstrap classes when starting an application (qiangxue) - Enh #2775: Added `yii\base\Application::bootstrap` and `yii\base\BootstrapInterface` to support running bootstrap classes when starting an application (qiangxue)
- Enh: Added support for using arrays as option values for console commands (qiangxue) - Enh: Added support for using arrays as option values for console commands (qiangxue)
- Enh: Added `favicon.ico` and `robots.txt` to default application templates (samdark) - Enh: Added `favicon.ico` and `robots.txt` to default application templates (samdark)
- Enh: Added `Widget::autoIdPrefix` to support prefixing automatically generated widget IDs (qiangxue) - Enh: Added `Widget::autoIdPrefix` to support prefixing automatically generated widget IDs (qiangxue)
......
...@@ -133,8 +133,9 @@ abstract class Application extends Module ...@@ -133,8 +133,9 @@ abstract class Application extends Module
*/ */
public $extensions = []; public $extensions = [];
/** /**
* @var array list of bootstrap classes. A bootstrap class must have a public static method named * @var array list of bootstrap classes or their configurations. A bootstrap class must implement
* `bootstrap()`. The method will be called during [[init()]] for every bootstrap class. * [[BootstrapInterface]]. The [[BootstrapInterface::bootstrap()]] method of each bootstrap class
* will be invoked at the beginning of [[init()]].
*/ */
public $bootstrap = []; public $bootstrap = [];
/** /**
...@@ -223,8 +224,9 @@ abstract class Application extends Module ...@@ -223,8 +224,9 @@ abstract class Application extends Module
{ {
$this->initExtensions($this->extensions); $this->initExtensions($this->extensions);
foreach ($this->bootstrap as $class) { foreach ($this->bootstrap as $class) {
/** @var Extension $class */ /** @var BootstrapInterface $bootstrap */
$class::bootstrap(); $bootstrap = Yii::createObject($class);
$bootstrap->bootstrap($this);
} }
parent::init(); parent::init();
} }
...@@ -243,9 +245,9 @@ abstract class Application extends Module ...@@ -243,9 +245,9 @@ abstract class Application extends Module
} }
} }
if (isset($extension['bootstrap'])) { if (isset($extension['bootstrap'])) {
/** @var Extension $class */ /** @var BootstrapInterface $bootstrap */
$class = $extension['bootstrap']; $bootstrap = Yii::createObject($extension['bootstrap']);
$class::bootstrap(); $bootstrap->bootstrap($this);
} }
} }
} }
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* BootstrapInterface is the interface that should be implemented by classes who want to participate in the application bootstrap process.
*
* The main method [[bootstrap()]] will be invoked by an application at the beginning of its `init()` method.
*
* Bootstrap classes can be registered in two approaches.
*
* The first approach is mainly used by extensions and is managed by the Composer installation process.
* You mainly need to list the bootstrap class of your extension in the `composer.json` file like following,
*
* ```json
* {
* // ...
* "extra": {
* "bootstrap": "path\\to\\MyBootstrapClass"
* }
* }
* ```
*
* If the extension is installed, the bootstrap information will be saved in [[Application::extensions]].
*
* The second approach is used by application code which needs to register some code to be run during
* the bootstrap process. This is done by configuring the [[Application::bootstrap]] property:
*
* ```php
* return [
* // ...
* 'bootstrap' => [
* "path\\to\\MyBootstrapClass1",
* [
* 'class' => "path\\to\\MyBootstrapClass2",
* 'prop1' => 'value1',
* 'prop2' => 'value2',
* ],
* ],
* ];
* ```
*
* As you can see, you can register a bootstrap class in terms of either a class name or a configuration class.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
interface BootstrapInterface
{
/**
* Bootstrap method to be called during application bootstrap stage.
* @param Application $app the application currently running
*/
public function bootstrap(Application $app);
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* Extension is the base class that may be extended by individual extensions.
*
* Extension serves as the bootstrap class for extensions. When an extension
* is installed via composer, the [[bootstrap()]] method of its Extension class (if any)
* will be invoked during the application initialization stage.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Extension
{
/**
* Initializes the extension.
* This method is invoked at the beginning of [[Application::init()]].
*/
public static function bootstrap()
{
}
}
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