zoukankan      html  css  js  c++  java
  • yii2 自动加载

    1.基本知识

    1. include, require

    2.如何实现类的自动加载 
    spl_autoload_register() 
    __autoload() 
     
    3.自动加载规范
    1.PSR-0:https://github.com/PizzaLiu/P...
    2.PSR-4:https://github.com/PizzaLiu/P...

    2.Yii2中代码自动加载的机制

    在Yii2.0的运行过程中主要由以下两个方法来实现代码的自动加载:
    1.path_to_your_project/vendor/composer/ClassLoader.php中的ClassLoader::loadClass()方法,这个方法是由composer提供的。

    2.类yiiBaseYii的autoload()方法,这个方法是由Yii2框架提供的

    Yii2中是如何实现代码的自动加载的?
    入口脚本两行代码:

    require(__DIR__ . '/../vendor/autoload.php');
    require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
    

     

    3.关于autoload.php:

    1.注册ComposerAutoloaderInit06ca19902d5e5679bb4a73b919aadb2a::loadClassLoader($class)为自动加载函数。这个loader负责引入了一个类:ClassLoader.php中的ComposerAutoloadClassLoader(),随后立即解除注册。

    2.注册vendor/composer/ClassLoader.php中的ClassLoader::loadClass($class)为自动加载函数,并利用配置文件(即vendor/composer目录下的autoload_*.php文件)对这个自动加载函数进行了初始化。这个函数实现了PSR-0,PSR-4,classmap等方式来自动加载。

    3.Require “vendor/composer/autoload_static.php”中的$files(作为全局函数使用) ??

    autoload_*.php的解释:

    1. autoload_static 主要是为了提高效率,相当于缓存

    当满足以下条件:
    1.PHP_VERSION_ID >= 50600
    2.&& !defined('HHVM_VERSION')
    3.&& (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
    则直接使用autoload_static文件而不采用上面的4个文件。

    2.autoload_namespaces.php 对应的是一些符合PSR-0的目录或文件

    3. autoload_psr4.php 包含的命名空间目录:vendor/yiisoft下满足psr-4的目录(包括yii命名空间,即yii api 中包含的类)

    4.autoload_classmap.php

    命令"composer dump-autoload -o"会生成这么一个文件,通过classmap方式,可以提高自动加载的效率
    (相比使用PSR-0或PSR-4自动加载,可以减少计算量和IO

    5.autoload_files.php 主要包括了需要立即require的文件( 通常是库文件,也可以是自定义的,引入作为全局函数使用)

    上面关于Closure::bind()的使用参考http://www.cnblogs.com/iforev...

    使用ComposerAutoloadClassLoader::loadClass()加载文件的顺序:

    • 1.先从classMap中找(时间复杂度O(1))
    • 2.查看是否文件之前已经查找过,证实不存在($missingClasses)
    • 3.如果有使用apc缓存的话从缓存中取
    • 4.查找文件名后缀为”.php”的文件

      - a)PSR-4 lookup:格式化类名,通过prefixLengthsPsr4,prefixDirsPsr4找到文件的绝对路径
      - b)PSR-4 fallback:根据$fallbackDirsPsr4查找根命名空间下的目录
      - c)PSR-0 lookup:分纯pear格式,pear+命名空间格式,根据prefixesPsr0找到文件的绝对路径
      - d)PSR-0 lookup:根据fallbackDirsPsr0查找根命名空间下的目录
      - e)PSR-0 include:如果允许使用include path方式的话,使用stream_resolve_include_path()返回绝对路径
      - f)找不到,返回false
    • 5.如果有使用HHVM的话,找后缀为”.hh”的文件,回到4下的具体查找(即a,b,c..)
    • 6.如果有使用apc缓存的话,将找到的文件的绝对路径存储到apc缓存中

    注意:
    1.在ClassLoader::findFileWithExtension($class, $ext)中实现了PSR-0和PSR-4的自动加载,其时间复杂度均为O(n2),相比于classmap的方式而言(时间复杂度为O(1))是低效的,因此在生产环境中可以采用composer命令"composer dump-autoload -o"进行优化

    4.其中Yii.php 的作用:

    1.定义类Yii(需要手动引入其父类的文件,而不是靠自动加载)
    2.注册Yii::autoload()为自动加载函数
    3.赋值Yii::$classMap (其值即yii2 api 中介绍的所有类,对应文件vendoryiisoftyii2classes.php)
    4.生成依赖注入容器:Yii::$container = new yiidiContainer();

    相对于ComposerAutoloadClassLoader::loadClass(),Yii.php所做的就简单明了许多了,如果所需加载的类在Yii::$classMap中有定义则直接通过它加载,没有的话就解析别名,然后加载。如果解析别名后依然找不到相应的文件路径,则使用composer提供的自动加载函数来加载(即ClassLoader::loadClass($class))

    Yii::autoload()主要能引入什么类?
    1.Yii::$classMap中定义的yii2核心类
    2.引入我们的应用中自己创建的类(依靠命名空间和别名,遵循PSR-4)

    最终注册了的自动加载方法以及顺序:
    1.Yii::autoload()
    2.vendorcomposerClassLoader.php中的ClassLoader::loadClass($class)

    .自动加载器YiiBase::autoload()

    • a)先从静态变量$classMap中找(从代码中看,这个貌似貌似没有用到)
    • b)再从静态变量$_coreClasses中找 (这个写死在YiiBase文件中了,包含了所有api)
    • c)如果允许 include_path,则直接include
    • d)不允许 include_path,根据self::$_includePaths 逐一查找文件,找到的话就include
    • e)按照类psr-4的方式查找( 与 .)(注意:这里这里需要用到一些常见的别名)
    • /**
           * Class autoload loader.
           * This method is provided to be invoked within an __autoload() magic method.
           * @param string $className class name
           * @return boolean whether the class has been loaded successfully
           */
          public static function autoload($className)
          {
              // use include so that the error PHP file may appear
              if(isset(self::$classMap[$className]))
                  include(self::$classMap[$className]);
              elseif(isset(self::$_coreClasses[$className]))//这个数组是写死在YiiBase中的,包含所有yii api
                  include(YII_PATH.self::$_coreClasses[$className]);
              else
              {
                  // include class file relying on include_path
                  if(strpos($className,'\')===false)  // class without namespace
                  {
                      if(self::$enableIncludePath===false)
                      {
                          foreach(self::$_includePaths as $path)
                          {
                              $classFile=$path.DIRECTORY_SEPARATOR.$className.'.php';
                              if(is_file($classFile))
                              {
                                  include($classFile);
                                  if(YII_DEBUG && basename(realpath($classFile))!==$className.'.php')
                                      throw new CException(Yii::t('yii','Class name "{class}" does not match class file "{file}".', array(
                                          '{class}'=>$className,
                                          '{file}'=>$classFile,
                                      )));
                                  break;
                              }
                          }
                      }
                      else
                          include($className.'.php');
                  }
                  else  // class name with namespace in PHP 5.3
                  {
                      $namespace=str_replace('\','.',ltrim($className,'\'));
                      if(($path=self::getPathOfAlias($namespace))!==false)
                          include($path.'.php');
                      else
                          return false;
                  }
                  return class_exists($className,false) || interface_exists($className,false);
              }
              return true;
          }

    参考: https://segmentfault.com/a/1190000010508018

  • 相关阅读:
    SpringBoot 线程池配置 定时任务,异步任务
    ArcMap 5 同一地区,多图层不能一起显示
    ArcMap 4 完全卸载ArcGIS
    ArcMap 3 矢量数据下载(下载、应用需谨慎)
    ArcMap 2 数据矢量化
    MODIS系列之NDVI(MOD13Q1)九:单一土地类型NDVI及时序图(以耕地类型为例)
    ArcMap 1 矢量数据和栅格数据
    ArcMap 0 (ArcGIS10.2安装(完善版--能解决常见问题))
    MODIS系列之NDVI(MOD13Q1)八:土地利用数据(又称地表覆盖数据)下载
    MODIS系列之NDVI(MOD13Q1)七:时间序列S-G滤波之Python
  • 原文地址:https://www.cnblogs.com/nkefww/p/12014417.html
Copyright © 2011-2022 走看看