Yii2框架类自动加载机制实例分析


Posted in PHP onMay 02, 2018

本文实例讲述了Yii2框架类自动加载机制。分享给大家供大家参考,具体如下:

在yii中,程序中需要使用到的类无需事先加载其类文件,在使用的时候才自动定位类文件位置并加载之,这么高效的运行方式得益于yii的类自动加载机制。

Yii的类自动加载实际上使用的是PHP的类自动加载,所以先来看看PHP的类自动加载。在PHP中,当程序中使用的类未加载时,在报错之前会先调用魔术方法__autoload(),所以我们可以重写__autoload()方法,定义当一个类找不到的时候怎么去根据类名称找到对应的文件并加载它。其中__autoload()方法被称为类自动加载器。当我们需要多个类自动加载器的时候,我们可以使用spl_autoload_register()方法代替__autoload()来注册多个类自动加载器,这样就相当于有多个__autoload()方法。spl_autoload_register()方法会把所有注册的类自动加载器存入一个队列中,你可以通过设置它的第三个参数为true来指定某个加载器放到队列的最前面以确保它最先被调用。Yii的类自动加载机制就是基于spl_autoload_register()方法的。

Yii的类自动加载机制要从它的入口文件index.php说起了,该文件源码如下:

<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);//运行模式
defined('YII_ENV') or define('YII_ENV', 'dev');//运行环境
require(__DIR__ . '/../../vendor/autoload.php');//composer的类自动加载文件
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');//yii的工具类文件(包含了yii类自动加载)
require(__DIR__ . '/../../common/config/bootstrap.php');//主要用于执行一些yii应用引导的代码
require(__DIR__ . '/../config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
  require(__DIR__ . '/../../common/config/main.php'),
  require(__DIR__ . '/../../common/config/main-local.php'),
  require(__DIR__ . '/../config/main.php'),
  require(__DIR__ . '/../config/main-local.php')
);
(new yii\web\Application($config))->run();

文件中第4、5行代码分别引入了composer的类自动加载文件和yii的工具类文件Yii.php,Yii.php文件源码如下:

require(__DIR__ . '/BaseYii.php');
class Yii extends \yii\BaseYii
{
}
spl_autoload_register(['Yii', 'autoload'], true, true);//注册yii的类自动加载器
Yii::$classMap = require(__DIR__ . '/classes.php');//引入类名到类文件路径的映射
Yii::$container = new yii\di\Container();

这个文件定义了Yii类继承自\yii\BaseYii,代码的第6行引入了classes.php文件,该文件源码:

return [
 'yii\base\Action' => YII2_PATH . '/base/Action.php',
 'yii\base\ActionEvent' => YII2_PATH . '/base/ActionEvent.php',
  ....//省略n多元素
 'yii\widgets\Pjax' => YII2_PATH . '/widgets/Pjax.php',
 'yii\widgets\PjaxAsset' => YII2_PATH . '/widgets/PjaxAsset.php',
 'yii\widgets\Spaceless' => YII2_PATH . '/widgets/Spaceless.php',
];

通过查看其源码可以看到,这个文件返回了一个从类名称到类文件路径的映射数组。这个数组被赋值给Yii::$classMap。代码的第7行调用了spl_autoload_register()方法注册了一个类自动加载器,这个类加载器为Yii::autoload(),这就是yii的类加载器了。同时这里通过把spl_autoload_register()方法第三个参数赋值为true,把yii的类加载器放在了加载器队列的最前面,所以当访问一个未加载的类的时候,yii的类自动加载器会最先被调用。

下面我们就来看看yii的类自动加载器Yii::autoload()到底做了些什么,这个方法实际上在yii\BaseYii类中,源码如下:

/**
 * 类自动加载器
 * @param type $className:要加载的类的名称
 * @return type
 * @throws UnknownClassException
 */
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::$classMap中事先定义,则类名必须以有效的根别名打头,否则无法找到对应文件。

就这样,在yii中无需在程序中事先加载一大堆可能会使用到的类文件,当使用到某个类的时候,yii的类自动加载器就会自动进行加载了,高效又便捷!

希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。

PHP 相关文章推荐
php自动适应范围的分页代码
Aug 05 PHP
php数组函数序列之in_array() 查找数组值是否存在
Oct 29 PHP
php中使用cookie来保存用户登录信息的实现代码
Mar 08 PHP
JSON在PHP中的应用介绍
Sep 08 PHP
PHP 获取文件权限函数介绍
Jul 11 PHP
ThinkPHP表单自动验证实例
Oct 13 PHP
PHP自定义函数获取URL中一级域名的方法
Aug 23 PHP
Zend Framework入门教程之Zend_Db数据库操作详解
Dec 08 PHP
thinkPHP+mysql+ajax实现的仿百度一下即时搜索效果详解
Jul 15 PHP
php array_map()函数实例用法
Mar 03 PHP
PHP实现chrome表单请求数据转换为接口使用的json数据
Mar 04 PHP
PHP常用字符串输出方法分析(echo,print,printf及sprintf)
Mar 09 PHP
PHP通过bypass disable functions执行系统命令的方法汇总
May 02 #PHP
购物车实现的几种方式优缺点对比
May 02 #PHP
PHP生成(支持多模板)二维码海报代码
Apr 30 #PHP
PHP实现的猴王算法(猴子选大王)示例
Apr 30 #PHP
PHP+MySQL高并发加锁事务处理问题解决方法
Apr 30 #PHP
PHP使用file_get_contents发送http请求功能简单示例
Apr 29 #PHP
PHP实现通过strace定位故障原因的方法
Apr 29 #PHP
You might like
php网站被挂木马后的修复方法总结
2014/11/06 PHP
PHP 使用 Imagick 裁切/生成缩略图/添加水印自动检测和处理 GIF
2016/02/19 PHP
Javascript 兼容firefox的一些问题
2009/05/21 Javascript
jQuery代码优化之基本事件
2011/11/01 Javascript
seajs1.3.0源码解析之module依赖有序加载
2012/11/07 Javascript
浅析js设置控件的readonly与enabled属性问题
2013/12/25 Javascript
基于jquery实现表格无刷新分页
2016/01/07 Javascript
超赞的jQuery图片滑块动画特效代码汇总
2016/01/25 Javascript
jQuery 翻页组件yunm.pager.js实现div局部刷新的思路
2016/08/11 Javascript
Angular页面间切换及传值的4种方法
2016/11/04 Javascript
jquery的父、子、兄弟节点查找,节点的子节点循环方法
2016/12/07 Javascript
新闻上下滚动jquery 超简洁(必看篇)
2017/01/21 Javascript
Vue2.0利用vue-resource上传文件到七牛的实例代码
2017/07/28 Javascript
JS传播事件、取消事件默认行为、阻止事件传播详解
2017/08/14 Javascript
angular基于ng-alain定义自己的select组件示例
2018/02/23 Javascript
使用vue的transition完成滑动过渡的示例代码
2018/06/25 Javascript
从Vuex中取出数组赋值给新的数组,新数组push时报错的解决方法
2018/09/18 Javascript
对angularJs中2种自定义服务的实例讲解
2018/09/30 Javascript
在angularJs中进行数据遍历的2种方法
2018/10/08 Javascript
vue实现todolist基本功能以及数据存储功能实例详解
2019/04/11 Javascript
JavaScript 继承 封装 多态实现及原理详解
2019/07/29 Javascript
Python实现的远程登录windows系统功能示例
2018/06/21 Python
Python3.6 + TensorFlow 安装配置图文教程(Windows 64 bit)
2020/02/24 Python
通过cmd进入python的步骤
2020/06/16 Python
一家专门经营包包的英国网站:MyBag
2019/09/08 全球购物
NYX Professional Makeup俄罗斯官网:世界知名的化妆品品牌
2019/12/26 全球购物
会计专业的自荐信
2013/12/12 职场文书
工作中个人的自我评价
2013/12/31 职场文书
公司新年寄语
2014/04/04 职场文书
超市活动计划书
2014/04/24 职场文书
火灾现场处置方案
2014/05/28 职场文书
学生实习证明范文
2014/09/28 职场文书
贵阳市党的群众路线教育实践活动党(工)委领导班子整改方案
2014/10/26 职场文书
Html5页面播放M4a音频文件
2021/03/30 HTML / CSS
JVM的类加载器和双亲委派模式你了解吗
2022/03/13 Java/Android
vue项目配置sass及引入外部scss文件
2022/04/14 Vue.js