1 版本
// yii\BaseYii\getVersion
public static function getVersion()
{
return '2.0.10';
}
2 创建Application
// web/index.php
new yii\web\Application($config)
创建一个app用于处理本次请求
// yii\base\Application.php
public function __construct($config = [])
{
Yii::$app = $this;
static::setInstance($this);
$this->state = self::STATE_BEGIN;
// 配置属性
$this->preInit($config);
// 注册error相关处理函数
$this->registerErrorHandler($config);
// 在基类的构造函数中将会调用init()函数
// 在init()中直接调用bootstrap()函数
// 先调用 web/Application::bootstrap()
// 再调用 base/Application::bootstrap()
Component::__construct($config);
}
// base/Application::bootstrap()
protected function bootstrap()
{
// 加载扩展清单中的文件, 默认使用 vendor/yiisoft/extensions.php
if ($this->extensions === null)
{
$file = Yii::getAlias('@vendor/yiisoft/extensions.php');
$this->extensions = is_file($file) ? include($file) : [];
}
// 创建这些扩展组件
// 如果这些组件实现了BootstrapInterface, 还会调用组件下的bootstrap函数
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__);
}
}
}
// 加载将要运行的一些组件, 这些组件配置在main.php, main-local.php中
// 'bootstrap' => ['log'],
// $config['bootstrap'][] = 'debug';
// $config['bootstrap'][] = 'gii';
// 开发模式下,默认加载3个: log, debug, gii
// 从$config中的配置信息变成base\Application中的属性$bootstrap经历以下步骤:
// Component::__construct --> Yii::configure($this, $config)
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);
}
// 如果这些组件实现了BootstrapInterface, 还会调用组件下的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__);
}
}
}
3 run过程
整个run过程经历以下过程:
public function run()
{
try {
// 处理请求前
$this->state = self::STATE_BEFORE_REQUEST;
$this->trigger(self::EVENT_BEFORE_REQUEST);
// 处理请求
$this->state = self::STATE_HANDLING_REQUEST;
$response = $this->handleRequest($this->getRequest());
// 处理请求前
$this->state = self::STATE_AFTER_REQUEST;
$this->trigger(self::EVENT_AFTER_REQUEST);
// 发送相应给客户端
$this->state = self::STATE_SENDING_RESPONSE;
$response->send();
$this->state = self::STATE_END;
return $response->exitStatus;
} catch (ExitException $e) {
$this->end($e->statusCode, isset($response) ? $response : null);
return $e->statusCode;
}
}
4 handleRequest
public function handleRequest($request)
{
// 如果设置了catchAll变量, 那么所有请求都会跳转到这里
// 示例:
// 假设网站维护, 不希望有人访问到内容
// 可以创建一个OfflineController控制器, 对应的views/offline/index.php可以写上
// <h1>网站正在维护中</h1>
// 然后在main.php中的$config中添加以下内容
// 'catchAll' => [ 'offline/index']
// 这样, 所有的访问都跳转到 网站正在维护中 的页面了
if (empty($this->catchAll))
{
try
{
list ($route, $params) = $request->resolve();
}
catch (UrlNormalizerRedirectException $e)
{
$url = $e->url;
if (is_array($url))
{
if (isset($url[0]))
{
// ensure the route is absolute
$url[0] = '/' . ltrim($url[0], '/');
}
$url += $request->getQueryParams();
}
return $this->getResponse()->redirect(Url::to($url, $e->scheme), $e->statusCode);
}
}
// 跳转到catchAll指定的route
else
{
$route = $this->catchAll[0];
$params = $this->catchAll;
unset($params[0]);
}
try
{
Yii::trace("Route requested: '$route'", __METHOD__);
$this->requestedRoute = $route;
$result = $this->runAction($route, $params);
...
}
...
}
5 runAction
创建Controller,并执行Controller对应的action
public function runAction($route, $params = [])
{
// 创建Controller
$parts = $this->createController($route);
if (is_array($parts))
{
list($controller, $actionID) = $parts;
$oldController = Yii::$app->controller;
Yii::$app->controller = $controller;
// 执行controller中的action
$result = $controller->runAction($actionID, $params);
if ($oldController !== null)
{
Yii::$app->controller = $oldController;
}
return $result;
}
else
{
$id = $this->getUniqueId();
throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
}
}
6 简述流程
- 通过Application创建app, 并且读入config, 装载扩展和组件
- 通过request解析被请求的路由
- app根据路由创建controller
- controller创建action
- 如果过滤器通过, 则会执行action
- action会渲染视图view
- view中的内容一般来自于model
- 渲染的结果通过response返回给客户端