yii2框架-yii2自身的自动加载(三)

上一节说完了composer的自动加载,下面我们来说一下yii2自身的自动加载。

在我们的入口文件,例如index.PHP,代码如下:

    <?php  
      
    // comment out the following two lines when deployed to production  
      
    defined('YII_DEBUG') or define('YII_DEBUG', true);  
    defined('YII_ENV') or define('YII_ENV', 'dev');  
      
    require(__DIR__ . '/../vendor/autoload.php');  
      
    require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');  
      
    $config = require(__DIR__ . '/../config/web.php');  
      
    (new yii\web\Application($config))->run();  
我们可以注意到require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php'),将yii2的核心的函数包含进去,下面看看Yii.php的代码:
    <?php  
    /** 
     * Yii bootstrap file. 
     * 
     * @link http://www.yiiframework.com/ 
     * @copyright Copyright (c) 2008 Yii Software LLC 
     * @license http://www.yiiframework.com/license/ 
     */  
      
    require(__DIR__ . '/BaseYii.php');  
      
    /** 
     * Yii is a helper class serving common framework functionalities. 
     * 
     * It extends from [[\yii\BaseYii]] which provides the actual implementation. 
     * By writing your own Yii class, you can customize some functionalities of [[\yii\BaseYii]]. 
     * 
     * @author Qiang Xue <qiang.xue@gmail.com> 
     * @since 2.0 
     */  
    class Yii extends \yii\BaseYii  
    {  
    }  
      
    spl_autoload_register(['Yii', 'autoload'], true, true);  
    Yii::$classMap = require(__DIR__ . '/classes.php');  
    Yii::$container = new yii\di\Container();  
首先包含BaseYii.php这个基础的yii文件,然后类Yii继承包含的Yii文件,命名空间是\yii\BaseYii,同时通过spl_autoload_register注册一个自动加载函数,这个函数是本类的autoload()函数,这些函数是在\yii\BaseYii中定义,而Yii类又继承\yii\BaseYii,所以Yii类相当于定义这些属性和方法。
而Yii::$classMap = require(__DIR__ . '/classes.php')这一句定义了命名空间与实际路径的映射关系,将返回一个数组的形式,保存在一个静态的变量中,那么这个变量有什么用呢?
下面我们再来看看spl_autoload_register注册的autoload()函数,在BaseYii.php中定义如下:
    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?");  
            }  
        }  

其中参数$className代表的是命名空间的类名,这个函数首先根据类名$className从$classMap是否可以找到对应设置的映射关系,如果找到对应的映射关系,就把文件对应的路径解释出来,赋值变量$classFile,如果找不到对应的映射关系,则将这个命名空间类执行:
$classFile = static::getAlias('@' . str_replace('\\', '/', $className) . '.php'
这句代码就是通过别名的方式来映射定义路径,比如:new \app\controllers\User,这个在$classMap肯定是找不到对应的关系的,所以这句代码会把\app\controllers\User先替换成@app/controllers/User,然后再通过static::getAlias('@app/controllers/User')解释别名,找到对应的实际文件路径,因为@app在配置文件中已经定义或者默认定义别名,getAlias()会负责解释,当然需要在@app下建立controllers的文件夹等,并将解释路径的值赋值变量$classFile,最后将这个路径包含进来。
所以总结一点:
我们可以在定义了别名的文件夹下@xxx,再建立文件夹aaa,然后定义文件bbb.php,那么在bbb.php的文件的命名空间就是xxx\aaa,这个文件的类名就是bbb。那么我们就可以在任何的地方直接用 new \xxx\aaa\bbb()的形式类创建实例。发生的过程大概就是这样子:
a)因为我们在入口文件首先注册composer的自动加载函数,放在spl的堆栈中
b)接着,我们又注册yii2自身的自动加载函数,放在spl的堆栈中,根据栈的后入先出的原则,yii2注册的函数将放在composer注册函数的前面,如果要用自动加载函数的话,首先用yii2自身注册的。
c)所以当我们 new \xxx\aaa\bbb 的时候,首先会从堆栈中调用yii2自身注册的autoload()函数,查找在yii2的本身是否存在对应的映射关系,如果找到,就直接包含文件进来,并实例化。如果找不到,再到yii2定义的别名的文件夹下面找,如果找到,就直接包含文件进来,并实例化。如果在yii注册的函数里都找不到,则接着调用spl堆栈的第二个自动函数,即composer自定义的autload()函数,按照函数定义的方式一直往下找,知道找到为止.如果确实找不到会返回错误。

原文链接 :http://blog.csdn.net/u012979009/article/details/51479504

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值