在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();

  文件中第五、六行代码分别引入了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,代码的第8行引入了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的类自动加载器就会自动进行加载了,高效又便捷!

Yii2之类自动加载的更多相关文章

  1. Yii2的深入学习--自动加载机制

    Yii2 的自动加载分两部分,一部分是 Composer 的自动加载机制,另一部分是 Yii2 框架自身的自动加载机制. Composer自动加载 对于库的自动加载信息,Composer 生成了一个  ...

  2. Yii2的深入学习--自动加载机制(转)

    Yii2 的自动加载分两部分,一部分是 Composer 的自动加载机制,另一部分是 Yii2 框架自身的自动加载机制. Composer自动加载 对于库的自动加载信息,Composer 生成了一个  ...

  3. YII框架的类自动加载机制

    YII之所以能实现快速的自动加载类文件,是因为它通过两种途径来实现. 先看文件 vendor\yiisoft\yii2\BaseYii.php 里面的 autoload 方法 public stati ...

  4. BPM配置故事之案例3-参与者与数据自动加载

    这才过了两天,阿海又来了. 阿海:公司决定改进管理方式,以后物资申请的申请人和申请部门要写具体使用人的名字和部门了. 小明:不是要让我改回去吧? 阿海:那太麻烦了,你能不能把申请人改成选择,选好人自动 ...

  5. Composer概述及其自动加载探秘

    composer概述 一开始,最吸引我的当属 Composer 了,因为之前从没用过 Composer . Composer 是PHP中用来管理依赖关系的工具,你只需在自己的项目中声明所依赖的外部工具 ...

  6. 让Lua自己把文件夹下面的所有文件自动加载起来吧

    没有想到我也做了一回标题党.其实这里边说的自动还是有夸大其词的部分.其实只是指定文件夹,然后根据指定文件夹数据,加载目录下边的内容而已. 怎么来进行Lua文件的加载 一般情况下,相关的功能需要给他创建 ...

  7. 如何实现一个php框架系列文章【3】支持psr4的自动加载类

    psr4自动加载规范https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-4-autoloader-cn.md 我们把第三方使用psr规范的类库放在v ...

  8. PHP 自动加载规范PSR-4

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  9. 构建自己的PHP框架之自动加载类中详解spl_autoload_register()函数

    在了解这个函数之前先来看另一个函数:__autoload. 一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数.看下面例子: printit.c ...

随机推荐

  1. jquery-easyUI第二篇【综合案例】

    基于easyUI开发的一个综合案例模版 <%@ page language="java" pageEncoding="UTF-8"%> <!D ...

  2. Web开发模式【Mode I 和Mode II的介绍、应用案例】

    开发模式的介绍 在Web开发模式中,有两个主要的开发结构,称为模式一(Mode I)和模式二(Mode II) 首先我们来理清一些概念吧: DAO(Data Access Object):主要对数据的 ...

  3. JDBC在javaweb中的应用之分页数据查询

    分页查询 分页查询是java web开发中经常使用到的技术.在数据库中数据量非常大的情况下,不适合将所有的数据全部显示到一个页面中,同时为了节约程序以及数据库的资源,就需要对数据进行分页查询操作. 通 ...

  4. [LeetCode] 344 Reverse String && 541 Reverse String II

    原题地址: 344 Reverse String: https://leetcode.com/problems/reverse-string/description/ 541 Reverse Stri ...

  5. 【京东账户】——Mysql/PHP/Ajax爬坑之用户登录

    一.引言 实现京东的账户项目,功能模块之一,用户登录.要用到的是Apach环境,Mysql.PHP以及Ajax. 二.依据功能创建库.表.记录 创建库:jd 创建表:登录表 添加三条记录 CREATE ...

  6. Message:Unable to locate element 问题解决方法

    Python断断续续学了有一段时间了,总感觉不找个小项目练练手心里没底,哪成想出门就遇到"拦路虎",一个脚本刚写完就运行报错,还好做足了心里准备,尝试自行解决. 或许网上有相关解决 ...

  7. 认识:ThinkPHP的编译缓存文件~runtime.php

    1.定义单入口文件(index.php) 在单入口index.php中不定义这两项时,会生成编译缓存文件~runtime.php define('RUNTIME_PATH','./App/Temp/' ...

  8. Java客户端调用.NET的WebService

    项目需要去调用.NET的WebSrevice,本身是Java,研究了半天,终于有些头绪,记下来. 1,新建.NET WebService.只在原方法上加上一个string类型的参数str [WebMe ...

  9. HDFS源码分析之NameNode(3)————RpcServer

    NameNodeRpcServer implements NamenodeProtocols NameNode支持核心即NameNodeRpcServer 实现ClientProtocol  支持客户 ...

  10. 零复制(zero copy)技术

    html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...