zoukankan      html  css  js  c++  java
  • yii2 beta版 执行流程

    yii2 beta版 执行流程

    自动加载

    1.composer的自动加载

    	//composer的加载实现了四种方式,可以看看
    	require(__DIR__ . '/../../vendor/autoload.php');
    

    composer的自动加载只加载其下载的组件....和yii框架的加载没有任何关系 2.yii的加载

    	spl_autoload_register(['Yii', 'autoload'], true, true);
    	Yii::$classMap = include(__DIR__ . '/classes.php');
    	Yii::$container = new yiidiContainer;
    

    这里使用spl_autoload_register把Yii::autoload注册成自动加载器,

    • 判断在不在$classMap中,如果有别名获取别名的文件路径
    • 如果不在$classMap中,则去除下划线,使用别名获取文件路径
    • 引入该文件,并判断是不是类或者接口或者trait
    	public static function autoload($className)
        {
            if (isset(static::$classMap[$className])) {
                $classFile = static::$classMap[$className];
                if ($classFile[0] === '@') {
                    $classFile = static::getAlias($classFile);
                }
            } elseif (strpos($className, '\') !== false) {
                $classFile = static::getAlias('@' . str_replace('\', '/', $className) . '.php', false);
                if ($classFile === false || !is_file($classFile)) {
                    return;
                }
            } else {
                return;
            }
    
            include($classFile);
    
            if (YII_DEBUG && !class_exists($className, false) && !interface_exists($className, false) && !trait_exists($className, false)) {
                throw new UnknownClassException("Unable to find '$className' in file: $classFile. Namespace missing?");
            }
        }
    

    Yii::$classMap中保存的是命名空间和文件实际路径的对应表,默认加载了所有yii提供的类 Yii::$container 实现了依赖注入, Yii::$app 继承serviceLocal..只实现了单例组件,其中属性_components保存的是对象,_definitions保存的是类,匿名函数或者对象

    引导前初始化配置

    1.检查配置中模块ID是不是存在
    2.检查配置中basePath,vendorPath,runtimePath,timeZone是否存在,并设置
    3.向配置中添加核心组件配置:
    base:log,view,formatter,i18n,mailer,urlManager,assetManager,security
    web:request,response,session,user,errorHandler
    4.如果启用了YII_ENABLE_ERROR_HANDLER错误处理,则会注册错误处理组件.然后从配置中卸载errorHandler,避免之后的引导再次添加组件.

    	    ini_set('display_errors', false);  //注意这里...
            set_exception_handler([$this, 'handleException']);
            set_error_handler([$this, 'handleError']);
            if ($this->memoryReserveSize > 0) {
                $this->_memoryReserve = str_repeat('x', $this->memoryReserveSize);
            }
            register_shutdown_function([$this, 'handleFatalError']);
    

    5.然后将配置中的值赋给applicaition

    属性 说明 所在文件
    $_events 使用on xxx 开通注册事件 yiiaseComponent
    $_behaviors 使用 as xxx开头注册行为 yiiaseComponent
    $_components 保存组件单例对象 yiidiServiceLocator
    $_definitions 保存组件的原始数据 yiidiServiceLocator
    $params 参数,是个数组 yiiaseModule
    $id 模块ID yiiaseModule
    $module 该模块的父模块 yiiaseModule
    $layout 布局 yiiaseModule
    $controllerMap 控制器地图 yiiaseModule
    $controllerNamespace 控制器命名空间 yiiaseModule
    $defaultRoute 默认路由 yiiaseModule
    $_basePath 模块的根目录 yiiaseModule
    $_viewPath 模块的视图目录 yiiaseModule
    $_layoutPath 模块的布局目录 yiiaseModule
    $_modules 子模块 yiiaseModule
    $_instances 这个不常用,获取当前请求模块的实例 yiiaseModule
    $controllerNamespace 'app\controllers' yiiaseApplication
    $name 应用名称 yiiaseApplication
    $version 版本 yiiaseApplication
    $charset 字符编码.默认utf8 yiiaseApplication
    $language 语言,默认en-US yiiaseApplication
    $sourceLanguage 源语言 yiiaseApplication
    $controller 当前的控制器实例 yiiaseApplication
    $layout 布局 yiiaseApplication
    $requestedRoute 请求的路由 yiiaseApplication
    $requestedAction 请求的动作 yiiaseApplication
    $requestedParams 请求的参数 yiiaseApplication
    $extensions 扩展 yiiaseApplication
    $bootstrap 引导 yiiaseApplication
    $state 状态 yiiaseApplication
    $defaultRoute 默认路由 yiiwebApplication
    $catchAll 捕捉所有 yiiwebApplication
    $controller 当前控制器实例 yiiwebApplication

    引导阶段

    • 1.初始化request组件
    • 2.设置@webroot和@web别名
    • 3.加载扩展extensions,如果没有设置extensions会读取@vendor/yiisoft/extensions.php中的扩展并设置别名,如果扩展可引导,则执行其bootstrap方法-----本身来讲扩展概念没什么用处,因为还是依靠modules来加载这些扩展
    • 4.加载bootstrap中设置的组件和模块或者类,如果引导类实现了BootstrapInterface接口则执行bootstrap的方法

    运行

    • 触发请求前事件EVENT_BEFORE_REQUEST,yii-debug中注册了该事件
    • 处理请求,如果catchAll不为空,则使用里面的路由.否则的话会解析获得路由和参数,
      然后执行动作action,返回响应Response,或者响应的data数据.
      		public function handleRequest($request)
      	    {
      	        if (empty($this->catchAll)) {
      	            list ($route, $params) = $request->resolve();
      	        } else {
      	            $route = $this->catchAll[0];
      	            $params = array_splice($this->catchAll, 1);
      	        }
      	        try {
      	            Yii::trace("Route requested: '$route'", __METHOD__);
      	            $this->requestedRoute = $route;
      	            $result = $this->runAction($route, $params);
      	            if ($result instanceof Response) {
      	                return $result;
      	            } else {
      	                $response = $this->getResponse();
      	                if ($result !== null) {
      	                    $response->data = $result;
      	                }
      
      	                return $response;
      	            }
      	        } catch (InvalidRouteException $e) {
      	            throw new NotFoundHttpException($e->getMessage(), $e->getCode(), $e);
      	        }
      	    }
      	
    • 动作的执行:首先会根据路由创建控制器.然后执行动作.
          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);
                  Yii::$app->controller = $oldController;
      
                  return $result;
              } else {
                  $id = $this->getUniqueId();
                  throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
              }
          }
      
      创建控制器
      	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 = '';
              }
      
              // module and controller map take precedence
              $module = $this->getModule($id);
              if ($module !== null) {
              	//如果有模块,则继续往下面找.这里是递归...能一直查询子模块
                  return $module->createController($route);
              }
      
              //查看控制器地图...一般控制器地图里的控制器..作为产品临时使用的页面
              if (isset($this->controllerMap[$id])) {
                  $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
      
                  return [$controller, $route];
              }
      		
      		//执行到最后,没有子模块的时候...则将id加上剩余的路径(可能有多个/文件夹)
              if (($pos = strrpos($route, '/')) !== false) {
                  $id .= '/' . substr($route, 0, $pos);
                  $route = substr($route, $pos + 1);
              }
      
              $controller = $this->createControllerByID($id);
              if ($controller === null && $route !== '') {
                  $controller = $this->createControllerByID($id . '/' . $route);
                  $route = '';
              }
      
              return $controller === null ? false : [$controller, $route];
          }
      
      获取模块
      	
      	public function getModule($id, $load = true)
          {
          //这一段是获取子模块的..在运行中是没有作用的..这一小部分可以当方法使用..
              if (($pos = strpos($id, '/')) !== false) {
                  // sub-module
                  $module = $this->getModule(substr($id, 0, $pos));
      
                  return $module === null ? null : $module->getModule(substr($id, $pos + 1), $load);
              }
      		
      		//这是返回模块
              if (isset($this->_modules[$id])) {
                  if ($this->_modules[$id] instanceof Module) {
                      return $this->_modules[$id];
                  } elseif ($load) {
                      Yii::trace("Loading module: $id", __METHOD__);
                      if (is_array($this->_modules[$id]) && !isset($this->_modules[$id]['class'])) {
                          $this->_modules[$id]['class'] = 'yiiaseModule';
                      }
                      /* @var $module Module */
                      $module = Yii::createObject($this->_modules[$id], [$id, $this]);
                      $module->setInstance($module);
                      return $this->_modules[$id] = $module;
                  }
              }
      
              return null;
          }
      
    • 触发请求后事件EVENT_AFTER_REQUEST,yii未注册事件
    • 响应发送
  • 相关阅读:
    [j2me]KSoap2在Nokia真机上可能导致SymbianOS error 28
    [J2ME]Nokia播放音乐时发生MediaException的解决办法
    [j2me]利用JLayerMECLDC0.2播放MP3的试验[1]
    [j2me]手机也可以玩播客(Podcast)! Geek开发说明[开源]
    [JavaME]手机申请移动分配的动态IP(3)?
    [流媒体]实例解析MMS流媒体协议,下载LiveMediaVideo[1][修正版,增加了带宽测试包]
    [JavaME]手机申请移动分配的动态IP(2)?
    [JavaME]手机是否能够申请到动态IP?
    [收藏]MIDlet如何签名的tutorial
    [流媒体]实例解析MMS流媒体协议,下载LiveMediaVideo[3]
  • 原文地址:https://www.cnblogs.com/zhepama/p/3851879.html
Copyright © 2011-2022 走看看