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作的文本留言本的例子(四)
Oct 09 PHP
缓存技术详谈―php
Dec 14 PHP
php+dojo 的数据库保存拖动布局的一个方法dojo 这里下载
Mar 07 PHP
PHP strtr() 函数使用说明
Nov 21 PHP
php for 循环语句使用方法详细说明
May 09 PHP
基于php设计模式中工厂模式详细介绍
May 15 PHP
PHP正则表达式 /i, /is, /s, /isU等介绍
Oct 23 PHP
详解php的socket通信
Aug 11 PHP
如何写php守护进程(Daemon)
Dec 30 PHP
php使用正则验证中文
Apr 06 PHP
thinkphp验证码的实现(form、ajax实现验证)
Jul 28 PHP
php 原生分页
Apr 01 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 number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
php的webservice的wsdl的XML无法显示问题的解决方法
2014/03/11 PHP
php实现连接access数据库并转txt写入的方法
2017/02/08 PHP
CSS+Jquery实现页面圆角框方法大全
2009/12/24 Javascript
jQuery 位置函数offset,innerWidth,innerHeight,outerWidth,outerHeight,scrollTop,scrollLeft
2010/03/23 Javascript
事件绑定之小测试  onclick &amp;&amp; addEventListener
2011/07/31 Javascript
js弹出层之1:JQuery.Boxy (二)
2011/10/06 Javascript
解析DHTML,JavaScript,DOM,BOM以及WEB标准的描述
2013/06/19 Javascript
jquery1.10给新增元素绑定事件的方法
2014/03/06 Javascript
Jquery代码实现图片轮播效果(一)
2015/08/12 Javascript
轻松学习jQuery插件EasyUI EasyUI创建RSS Feed阅读器
2015/11/30 Javascript
JavaScript实现ASC转汉字及汉字转ASC的方法
2016/01/23 Javascript
使用Bootstrap typeahead插件实现搜索框自动补全的方法
2016/07/07 Javascript
微信小程序之绑定点击事件实例详解
2017/07/07 Javascript
jQuery图片查看插件Magnify开发详解
2017/12/25 jQuery
angular json对象push到数组中的方法
2018/02/27 Javascript
三分钟教你用Node做一个微信哄女友(基友)神器(面向小白)
2019/06/21 Javascript
解决LayUI数据表格复选框不居中显示的问题
2019/09/25 Javascript
Python中文件的写入读取以及附加文字方法
2019/01/23 Python
django中forms组件的使用与注意
2019/07/08 Python
用Python写一个自动木马程序
2019/09/17 Python
python编程进阶之类和对象用法实例分析
2020/02/21 Python
html+css实现自定义图片上传按钮功能
2019/09/04 HTML / CSS
html5使用canvas画三角形
2014/12/15 HTML / CSS
送给他或她的礼物:FUN.com
2018/08/17 全球购物
高中军训感想300字
2014/03/04 职场文书
竞聘书怎么写,如何写?
2014/03/31 职场文书
党的群众路线教育实践活动批评与自我批评范文
2014/10/16 职场文书
2014年个人师德工作总结
2014/12/04 职场文书
2015年高三班主任工作总结
2015/05/21 职场文书
Redis安装启动及常见数据类型
2021/04/14 Redis
go原生库的中bytes.Buffer用法
2021/04/25 Golang
pytorch常用数据类型所占字节数对照表一览
2021/05/17 Python
Python 如何解决稀疏矩阵运算
2021/05/26 Python
Nginx 常用配置
2022/05/15 Servers
教你使用RustDesk 搭建一个自己的远程桌面中继服务器
2022/08/14 Servers