我是在  backend 一步步打印的   很多地方我也是很模糊 。后来发现一位大神的文章(http://www.yiichina.com/tutorial/773)  参考文章自己动手开始写的  至于后来的 第一遍 很粗糙 慢慢完善。
希望对自己有帮助 希望各位积极指点 和后面不详细的地方 作补充。 我也会继续完善 。 先从入口开始
$application = new yii\web\Application($config);  //实例化 Application
$application->run();
这是  Application 的方法
class Application extends \yii\base\Application   
在Application类中 首先看有没有构造方法  没有找到  so  就去父类中找(\yii\base\Application)

在\yii\base\Application  
..........
public function __construct($config = [])
{
Yii::$app = $this;  // $this 代表 object(yii\web\Application)
static::setInstance($this);  // 在这个方法中把这个类中所有的方法属性都放到一个数组中@@@@@请看下面 $this->state = self::STATE_BEGIN; $this->preInit($config);  //看下面有解释 $this->registerErrorHandler($config);//暂不做解释 加载异常类 以后研究   Component::__construct($config);
}
..........
@@@@@
public static function setInstance($instance)
{
if ($instance === null) {    //$instance不为空 代表的$this(object(yii\web\Application))
        unset(Yii::$app->loadedModules[get_called_class()]);
} else {              //get_class($instance) -> "yii\web\Application"
Yii::$app->loadedModules[get_class($instance)] = $instance;
}
}
这样 Yii::$app 就可以调用 该类中的方法 属性 以及父类中的方法。

$this->preInit($config);//

*****preInit****方法

主要是获取到配置文件中的数据  处理配置文件的数据 设置别名等等
public function preInit(&$config)
{
if (!isset($config['id'])) {
throw new InvalidConfigException('The "id" configuration for the Application is required.');
}
if (isset($config['basePath'])) {
$this->setBasePath($config['basePath']); //拿这个做例子
unset($config['basePath']); 。。。部分代码省略。。。。。
  
  public function setBasePath($path)
  {              
      var_dump($path);die;   //     "/var/www/testyii2/backend"     
   parent::setBasePath($path);     //该方法中设置 $this->_basePath = $app;  $app=/var/www/testyii2/backend
      Yii::setAlias('@app', $this->getBasePath());   so  此时  @app  就等于  /var/www/testyii2/backend
  }
好了现在回到 preInit()方法中
*******end*****
$this->registerErrorHandler($config);简单看下吧
$this->set('errorHandler', $config['components']['errorHandler']);
我打印了下 var_dump($this->get('errorHandler')) 应该是 定义一些错误方法和属性等等 看下图


最后看这个方法
Component::__construct($config);  调用了 object 方法中的 构造方法
object(类):
public function __construct($config = [])
{
if (!empty($config)) {
Yii::configure($this, $config);  //找到Yii类 该类中没有configure 方法 然而继承了 baseyii so 去baseyii类中找
                          //
}
$this->init();
}
。。。。。
//baseyii类
public static function configure($object, $properties)
{
foreach ($properties as $name => $value) {
$object->$name = $value;
}
return $object;
}
//该方法 中 $object ==object类 循环吧配置文件中的 数据 复制给 object对象中的属性和值  最终由于object 是yii\web\Application 的最终父类 还有在上面中定义了别名@app

  // so  可以Yii::$app->配置参数来访问配置文件中的内容

****end***

分析
$this->init();  在object类中   class Component extends Object  component继承的object
Component::__construct($config);   在base/Application  继承了 Module 类 
so 看module 中的init方法()
//module 中的init 方法
public function init()
{
if ($this->controllerNamespace === null) {  //取出控制器命名空间。
$class = get_class($this);
if (($pos = strrpos($class, '\\')) !== false) {
$this->controllerNamespace = substr($class, 0, $pos) . '\\controllers';
}
}
}

完毕

回到起点 看index.php中的

$application->run();   在Application类中没有找到run方法   Application 继承 base\Application类

\yii\base\Application.php   中的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调用的是 yii\web\Application.php 中的方法看下面
        $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; }
      }
//web/Application 中的 handleRequest()
public function handleRequest($request)
{
if (empty($this->catchAll)) {
list ($route, $params) = $request->resolve();  //取出路由及参数
} 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);//运行控制器中的Acition,下面有详细介绍 base/application 中没有so 找到module 中的runaction()
if ($result instanceof Response) {
return $result;
} else {
$response = $this->getResponse();
if ($result !== null) {
$response->data = $result;
} return $response;
}
} catch (InvalidRouteException $e) {
throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'), $e->getCode(), $e);
}
}
// class Module

public function runAction($route, $params = [])
{
$parts = $this->createController($route);//根据路由创建控制器 看下面
if (is_array($parts)) {
/* @var $controller Controller */
list($controller, $actionID) = $parts;
$oldController = Yii::$app->controller;
Yii::$app->controller = $controller;
$result = $controller->runAction($actionID, $params);//创建方法执行控制器里的action actionId ==index( 控制器/index(这里表示方法))
Yii::$app->controller = $oldController; return $result;
} else {
$id = $this->getUniqueId();
throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
}
}
$this->createController()
$this->createController()  //创建控制器
public function createController($route)
{
if ($route === '') {
$route = $this->defaultRoute;
} // double slashes or leading/ending slashes may cause substr problem
$route = trim($route, '/');
if (strpos($route, '//') !== false) {
return false;
} if (strpos($route, '/') !== false) {
list ($id, $route) = explode('/', $route, 2);
} else {
$id = $route;
$route = '';
}
echo   $route //--->"backend/default/index"
// module and controller map take precedence
    if (isset($this->controllerMap[$id])) {  //不进入
$controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
return [$controller, $route];
}
$module = $this->getModule($id);
if ($module !== null) {        //不进入
return $module->createController($route);
} if (($pos = strrpos($route, '/')) !== false) {
$id .= '/' . substr($route, 0, $pos);  
$route = substr($route, $pos + 1);  
}
//$id = backend/default"   (模块/控制器)   $route =index   方法
    $controller = $this->createControllerByID($id);  //下面分析用颜色查找
if ($controller === null && $route !== '') {  //进入
$controller = $this->createControllerByID($id . '/' . $route); // 根据给定的控制器标识创建一个控制器。看下面
$route = '';
} return $controller === null ? false : [$controller, $route];
}
 
public function createControllerByID($id)
{
$pos = strrpos($id, '/');
if ($pos === false) {
$prefix = '';
$className = $id;
} else {
$prefix = substr($id, 0, $pos + 1);    //backend 模块
$className = substr($id, $pos + 1);    //default 控制器
} if (!preg_match('%^[a-z][a-z0-9\\-_]*$%', $className)) {
return null;
}
// preg_match('%^[a-z0-9_/]+$%i', $prefix) ===1
    if ($prefix !== '' && !preg_match('%^[a-z0-9_/]+$%i', $prefix)) {      
        return null;
}
    $className = str_replace(' ', '', ucwords(str_replace('-', ' ', $className))) . 'Controller';  
$className = ltrim($this->controllerNamespace . '\\' . str_replace('/', '\\', $prefix) . $className, '\\');
if (strpos($className, '-') !== false || !class_exists($className)) {
return null;
}
  
if (is_subclass_of($className, 'yii\base\Controller')) {
$controller = Yii::createObject($className, [$id, $this]);  //创建了控制器对象
return get_class($controller) === $className ? $controller : null;
} elseif (YII_DEBUG) {
throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller.");
} else {
return null;
}
}
Yii/BaseYii.php
public static function createObject($type, array $params = [])
{
if (is_string($type)) {
return static::$container->get($type, $params);  //返回请求类的是例 这边就不往下追了 本人能力有限啊 唉~无线惆怅中~~~
} elseif (is_array($type) && isset($type['class'])) {
$class = $type['class'];
unset($type['class']);
return static::$container->get($class, $params, $type);
} elseif (is_callable($type, true)) {
return static::$container->invoke($type, $params);
} elseif (is_array($type)) {
throw new InvalidConfigException('Object configuration must be an array containing a "class" element.');
} else {
throw new InvalidConfigException('Unsupported configuration type: ' . gettype($type));
}
}
****end** 小部分结束(创建控制器部分)
//承接上面的方法继续分析
$controller->runAction($actionID, $params);
namespace  yii\base;   //命名空间
class Controller extends Component implements ViewContextInterface{
public function runAction($id, $params = [])
{
  $action = $this->createAction($id);  ////创建action  暂时不补全代码了 类啊。。。后续补上。
  //打印$action == yii\base\InlineAction 对象

   if ($action === null) {
  throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $id);
  }   Yii::trace("Route to run: " . $action->getUniqueId(), __METHOD__);   if (Yii::$app->requestedAction === null) {
   Yii::$app->requestedAction = $action;
  }   $oldAction = $this->action;    //NULL
  $this->action = $action;   $modules = [];
  $runAction = true;   // call beforeAction on modules   // 加载默认模块如:Application log等。再调用模块内的beforeAction方法
  foreach ($this->getModules() as $module) {
   if ($module->beforeAction($action)) {
   array_unshift($modules, $module);
   } else {
   $runAction = false;
   break;
   }
  } $result = null; if ($runAction && $this->beforeAction($action)) { //执行beforeAction
// run the action
$result = $action->runWithParams($params);   //执行控制器里的action $result = $this->afterAction($action, $result); //执行afterAction

    // call afterAction on modules
foreach ($modules as $module) {
/* @var $module Module */
$result = $module->afterAction($action, $result);
}
} $this->action = $oldAction; return $result;
}
}

//打印action  yii\base\InlineAction
public function runWithParams($params)
{
$args = $this->controller->bindActionParams($this, $params);
Yii::trace('Running action: ' . get_class($this->controller) . '::' . $this->actionMethod . '()', __METHOD__);
if (Yii::$app->requestedParams === null) {
Yii::$app->requestedParams = $args;
} return call_user_func_array([$this->controller, $this->actionMethod], $args);
}

yii2 源码分析1从入口开始的更多相关文章

  1. Yii2 源码分析 入口文件执行流程

    Yii2 源码分析  入口文件执行流程 1. 入口文件:web/index.php,第12行.(new yii\web\Application($config)->run()) 入口文件主要做4 ...

  2. Yii2源码分析(一):入口

    写在前面,写这些随笔是记录下自己看Yii2源码的过程,可能会有些流水账,大部分解析放在注释里说明,由于个人水平有限,有不正确的地方还望斧正. web入口文件Index.php // 定义全局的常量,Y ...

  3. MongoDB源码分析——mongo主程序入口分析

    Edit   源码版本为MongoDB 2.6分支 mongo主程序入口分析 mongo是MongoDB提供的一个执行JavaScript脚本的客户端工具,可以用来和服务端交互,2.6版本的Mongo ...

  4. MYC编译器源码分析之程序入口

    前文.NET框架源码解读之MYC编译器讲了MyC编译器的架构,整个编译器是用C#语言写的,上图列出了MyC编译器编译一个C源文件的过程,编译主路径如下: 首先是入口Main函数用来解析命令行参数,读取 ...

  5. yii2 源码分析 object类分析 (一)

    转载请注明链接http://www.cnblogs.com/liuwanqiu/p/6737327.html yii2基本上所有的类都是继承的object类,下面就来分析一下object类吧 obje ...

  6. yii2 源码分析 model类分析 (五)

    模型类是数据模型的基类.此类继承了组件类,实现了3个接口 先介绍一下模型类前面的大量注释说了什么: * 模型类是数据模型的基类.此类继承了组件类,实现了3个接口 * 实现了IteratorAggreg ...

  7. yii2 源码分析Action类分析 (六)

    Action类是控制器的基类, <?php namespace yii\base; use Yii; /** * Action是所有控制器动作类的基类,它继承组件类 * * 动作提供了重用动作方 ...

  8. yii2 源码分析Behavior类分析 (四)

    Behavior类是所有事件类的基类,它继承自object类 Behavior类的前面注释描述大概意思: * Behavior类是所有事件类的基类 * * 一个行为可以用来增强现有组件的功能,而不需要 ...

  9. yii2 源码分析Event类分析 (三)

    转载请注明链接:http://www.cnblogs.com/liuwanqiu/p/6739880.html Event是所有事件的基类,它继承Object类 Event类上面的注释的大致意思: * ...

随机推荐

  1. pgrep 和 pkill 使用小记

    在停止指定进程时,经常使用如下命令: kill `ps aux | grep -w program_name | grep -v grep | awk '{print $2}'` 使用 pgrep 和 ...

  2. 【Android】SDK工具学习 - adb

    ADB(Android Debug Bridge) 小白笔记 学习资料 adb简要介绍 adb 是一个 C/S 架构的命令行工具,主要由 3 部分组成: 运行在 PC 端的 Client : 可以通过 ...

  3. RabbitMQ学习系列二-C#代码发送消息

    RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列 http://www.80iter.com/blog/1437455520862503 上一篇已经讲了Rabbi ...

  4. Oracle Sql Developer 连接oracle

    PL/Sql 初次使用需要配置文件内容,对于我这种Oracle新手来说各种配置有点凌乱,所以果断选择Sql Developer. 选择它是因为初次使用的时候它不用想PL/Sql那样配置文件,而只需要添 ...

  5. 【spring源码学习】spring的IOC容器之自定义xml配置标签扩展namspaceHandler向IOC容器中注册bean

    [spring以及第三方jar的案例]在spring中的aop相关配置的标签,线程池相关配置的标签,都是基于该种方式实现的.包括dubbo的配置标签都是基于该方式实现的.[一]原理 ===>sp ...

  6. k8s api server ha 连接配置问题

    常见的lb 负载有硬件的f5 big-ip  ,同时对于互联网公司大家常用的是nginx  haproxy 了解k8s 集群高可用的都知道 api server  是无状态的(etcd 解决了),但是 ...

  7. Oracle12c版64位客户端安装步骤(32位安装步骤一样)

    1.双击setup.exe文件 2.下一步 3.下一步   4.安装 5.完成

  8. 使用 Git 来备份 MySQL 数据库

    使用 Git 来备份 MySQL 数据库 使用 mysqldump 导出 sql 文件 使用 git pull 提交到仓库 将脚本加入任务管理 mysqldump 导出时需要以下参数. --skip- ...

  9. bzoj 4319 cerc2008 Suffix reconstruction——贪心构造

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4319 如果字符集有 5e5 那么大的话,挨个填上去就行了.但只有26个字符,所以要贪心地尽量 ...

  10. OPCDAAuto.dll的C#使用方法浅析

    上次研究了.Net版本的OPC API dll,这次我采用OPCDAAuto.dll来介绍使用方法.以下为我的源代码,有详细的注释无需我多言.编译平台:VS2008SP1.WINXP.KEPServe ...