bootstrap是指应用开始解析并处理请求之前,一个预先准备环境的阶段,也就是一个前期的初始化 过程,也就是说,在执行helloworld之前,需要执行的代码部分。
启动这个过程会在两个地方,一个是index.php的入口文件,一个是application的bootstrap过程。
1.index.php入口文件: 大致为composer文件自动加载器,yii的文件自动加载器,已经配置文件的合并,环境参数的设置。然后通过\yii\base\application->run()方法创建一个应用主体application。
2.
调用 yii\base\Application::preInit()(预初始化)方法,配置一些高优先级的应用属性,比如 yii\base\Application::basePath 属性。
注册yii\base\Application::errorHandler。
通过给定的应用配置初始化应用的各属性。
通过调用 yii\base\Application::init()(初始化)方法,它会顺次调用 yii\base\Application::bootstrap() 从而运行引导组件。
加载扩展清单文件(extension manifest file) vendor/yiisoft/extensions.php。
创建并运行各个扩展声明的 引导组件(bootstrap components)。
创建并运行各个 应用组件 以及在应用的 Bootstrap 属性中声明的各个 模块(modules)组件(如果有)。
总体来说就是:配置参数,配置error的处理,然后执行application的bootstrap()方法
application的bootstrap方法依次:
1.加载插件配置,也就是文件:@vendor/yiisoft/extensions.php中的bootstrap配置,
2.配置的组件(component)和模块的bootstrap配置。
application的bootstrap代码如下:
protected function bootstrap()
{
if ($this->extensions === null) {
$file = Yii::getAlias('@vendor/yiisoft/extensions.php');
$this->extensions = is_file($file) ? include($file) : [];
}
foreach ($this->extensions as $extension) {
if (!empty($extension['alias'])) {
foreach ($extension['alias'] as $name => $path) {
Yii::setAlias($name, $path);
}
}
if (isset($extension['bootstrap'])) {
$component = Yii::createObject($extension['bootstrap']);
if ($component instanceof BootstrapInterface) {
Yii::trace('Bootstrap with ' . get_class($component) . '::bootstrap()', __METHOD__);
$component->bootstrap($this);
} else {
Yii::trace('Bootstrap with ' . get_class($component), __METHOD__);
}
}
}
foreach ($this->bootstrap as $class) {
$component = null;
if (is_string($class)) {
if ($this->has($class)) {
$component = $this->get($class);
} elseif ($this->hasModule($class)) {
$component = $this->getModule($class);
} elseif (strpos($class, '\\') === false) {
throw new InvalidConfigException("Unknown bootstrapping component ID: $class");
}
}
if (!isset($component)) {
$component = Yii::createObject($class);
}
if ($component instanceof BootstrapInterface) {
Yii::trace('Bootstrap with ' . get_class($component) . '::bootstrap()', __METHOD__);
$component->bootstrap($this);
} else {
Yii::trace('Bootstrap with ' . get_class($component), __METHOD__);
}
}
}
先执行extensions的,在一次执行在bootstrap中的配置,按照配置的顺序依次执行
2.1:在插件扩展中加入bootstrap
'fancyecommerce/fec' =>
array (
'name' => 'fancyecommerce/fec',
'version' => '1.1.2.1',
'bootstrap' => array
'alias' =>
array (
'@fec' => $vendorDir . '/fancyecommerce/fec',
),
'bootstrap': 'fecadmin\\mywidget\\MyBootstrapClass'
),
namespace fecadmin\mywidget;
use yii\base\BootstrapInterface;
use yii\base\Application;
class MyBootstrapClass implements BootstrapInterface
{
public function bootstrap($app)
{
$app->on(Application::EVENT_BEFORE_REQUEST, function () {
// do something here
});
}
}
这样就会在bootstrap过程中执行这个类里面的bootstrap()方法:
参考文献:http://www.yiiframework.com/doc-2.0/guide-structure-extensions.html#bootstrapping-classes,在这里可以查看如何在插件制作的时候在composer.json中进行配置,配置后的内容将被写入extensions.php文件中。
2.2 在模块中加入bootstrap配置
如果是模块,则执行模块对应的Module文件,
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = 'yii\gii\Module';
上面的配置,配置了模块 gii,并且把gii加入了bootstrap,因此,就会执行\yii\gii\Module->bootstrap();
gii的bootstrap()为:
class Module extends \yii\base\Module implements BootstrapInterface
{
public function bootstrap($app)
{
if ($app instanceof \yii\web\Application) {
$app->getUrlManager()->addRules([
$this->id => $this->id . '/default/index',
$this->id . '/' => $this->id . '/default/view',
$this->id . '//' => $this->id . '//',
], false);
} elseif ($app instanceof \yii\console\Application) {
$app->controllerMap[$this->id] = [
'class' => 'yii\gii\console\GenerateController',
'generators' => array_merge($this->coreGenerators(), $this->generators),
'module' => $this,
];
}
}
修改app对应的UrlManager 和controllerMap。
需要注意的是要想bootstrap()执行,一定要实现BootstrapInterface接口,否则,不会被执行,因为在Application->bootstrap函数中有一个判断:
if ($component instanceof BootstrapInterface) {
Yii::trace('Bootstrap with ' . get_class($component) . '::bootstrap()', __METHOD__);
$component->bootstrap($this);
}
2.3 如果该配置是组件,则执行组件文件对应的class里面的bootstrap方法
同样,和上面的module类型,需要做的是:
2.3.1 在config.php中加入配置,譬如log:
'bootstrap' => ['log'],
2.3.2 让组件所在的class实现接口:use yii\base\BootstrapInterface;
2.3.3 在组件所在的class实现方法bootstrap($app)
这样就可以了。