yii2 源码分析1从入口开始



我是在  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  代表这个类
        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(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 = $p;  $p=/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
            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  暂时不补全代码了 类啊。。。后续补上。   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;$this->action = $action;

$modules = [];$runAction = true;

  // call beforeAction on modules  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);}
时间: 2024-11-03 21:13:30

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

yii2源码分析之执行基本流程

用yii2框架用了将近2年,一直都没有去看过它底层源码,  马上快不用了,最近对其源码研究一番,哈哈 废话少说,上代码, 入口文件是web/index.php <?php defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); //这行我在composer autoload流程已经分析过 require __DIR__ . '/../vendor/auto

Android4.0 Launcher 源码分析2——Launcher入口及Launcher.xml的加载

2.Launcher入口及Launcher.xml的加载 2.1 Launcher入口 1) LauncherApplication 我们在源代码中可以找到LauncherApplication, 它继承了Application类,当整个Launcher启动时,它就是整个程序的入口.我们先来看它们在AndroidManifest.xml中是怎么配置的. 1 <application 2 android:name="com.android.launcher2.LauncherApplicat

yii2源码分析之组件实例化流程

读本篇文章,建议先看看我之前的文章php依赖注入 到此,现在我们正式开始分析yii2框架组件构造流程 我们先从yii\di\ServiceLocator(服务定位器)入手吧!!让我们先看个实例: use yii\di\ServiceLocator; use yii\caching\FileCache; $locator = new ServiceLocator; // 通过一个可用于创建该组件的类名,注册 "cache" (缓存)组件. $locator->set('cache'

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

模型类是数据模型的基类.此类继承了组件类,实现了3个接口 先介绍一下模型类前面的大量注释说了什么: * 模型类是数据模型的基类.此类继承了组件类,实现了3个接口 * 实现了IteratorAggregate(聚合式迭代器)接口,实现了ArrayAccess接口,可以像数组一样访问对象,这两个接口是php自带 * Arrayable接口是yii2框架自带 * 模型实现了以下常用功能: * * - 属性声明: 默认情况下,每个公共类成员都被认为是模型属性 * - 属性标签: 每个属性可以与用于显示目

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

Action类是控制器的基类, <?php namespace yii\base; use Yii; /** * Action是所有控制器动作类的基类,它继承组件类 * * 动作提供了重用动作方法代码的方法, * Action类中的动作方法可以用于多个控制器或不同的项目中. * * 派生类必须实现一个方法叫` run() ` * 当请求操作时,该方法将由控制器调用 * `run()` 方法的参数由用户根据他们的名字自动输入的值确定 * 例如, `run()`方法以以下形式定义 * * ```ph

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

Action类是控制器的基类, <?php namespace yii\base; use Yii; /** * Action是所有控制器动作类的基类,它继承组件类 * * 动作提供了重用动作方法代码的方法, * Action类中的动作方法可以用于多个控制器或不同的项目中. * * 派生类必须实现一个方法叫` run() ` * 当请求操作时,该方法将由控制器调用 * `run()` 方法的参数由用户根据他们的名字自动输入的值确定 * 例如, `run()`方法以以下形式定义 * * ```ph

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

Behavior类是所有事件类的基类,它继承自object类 Behavior类的前面注释描述大概意思: * Behavior类是所有事件类的基类 * * 一个行为可以用来增强现有组件的功能,而不需要修改它的代码. * 用来增强现有组件的功能而不修改它的代码.它可以添加自己的方法和属性组件 * 使他们可以直接通过组件访问.还可以响应组件触发的事件,拦截正常的代码执行. class Behavior extends Object { /** * 要附加行为对象的组件 */ public $owne

yii2 源码分析 Component类分析 (二)

转载请注明链接http://www.cnblogs.com/liuwanqiu/p/6739538.html 组件(component),是Yii框架的基类,实现了属性.事件.行为三类功能,它集成自object类 类前面的大部分注释: 1.事件在定义的类中唯一名称标示,事件名称区分大小写 2.将事件处理程序到附加到事件,是用on 3.有三种事件函数的调用方法,匿名函数调用,对象调用,静态方法调用,全局函数调用 4.可以在配置中配置组件,使用方式是: [ 'on add' => function

Hadoop源码分析—— Job任务的程序入口

这篇文章大致介绍Hadoop Job的程序是如何启动的. 通常用Java编写的Hadoop MapReduce程序是通过一个main方法作为程序的整个入口,如下: public static void main(String[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new CalculateSumJob(),args); System.exit(res);} 可以看到这个Job任务的MapR