四、逐行阅读Yii2.0.43源码_Yii框架文件BaseYii.php(2)

1. autoload方法, Yii框架的注册的自动加载函数,这个方法将优先于composer的autoload执行

解析顺序:

第一步:查找类映射

第二步:查找路径别名

/**
     * Yii框架的注册的自动加载函数,
     * 这个方法将优先于composer的autoload执行
     */
    public static function autoload($className)
    {
        if (isset(static::$classMap[$className])) {
            // 先从 类映射$classMap中查找, $classMap初始化的时候,
            // 保存了框架预先定义好的很多 类-->文件路径的映射
            $classFile = static::$classMap[$className];

            if (strpos($classFile, '@') === 0) {
                //映射的数组中可以定义 路径别名,
                //路径别名以 '@'开头,这里调用getAlias方法来解析
                //getAlias方法返回路径别名对应的真实路径
                $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不存在,脚本也不会停止执行
        //只是会给出一个警告
        include $classFile;

        // 如果是调试模式,并且在(class,interface和 trait)中没有发现$className,抛出UnknownClassException异常
        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?");
        }
    }

2. createObject方法,基于类名,配置数组或者php调用创建一个对象

解析顺序:

先从字符串到php调用再到配置数组,其他情况,抛出异常

/**
     * 使用给定的配置创建对象。
     * 可以基于 类名称,配置数组,或者匿名函数创建一个对象
     * 1. 基于类名称 $object = Yii::createObject('yii\db\Connection');
     * 2. 基于配置数组 $object = Yii::createObject([
     *     'class' => 'yii\db\Connection',
     *     'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
     *     'username' => 'root',
     *     'password' => '',
     *     'charset' => 'utf8',
     *  ]);
     * 3. 创建一个对象,传递两个构造参数 $object = \Yii::createObject('MyClass', [$param1, $param2]);
     *
     * $type:可以是 字符串, 数组,或者是一个php调用
     * $params 数组
     */
    public static function createObject($type, array $params = [])
    {
        //1.基于字符串创建对象
        //如果是 字符串,则从容器获取
        // static::$container是一个\yii\di\Container容器, 在Yii.php中初始化
        if (is_string($type)) {
            return static::$container->get($type, $params);
        }

        //2.基于php调用创建对象
        //如果是一个php调用,则从容器获取
        if (is_callable($type, true)) {
            return static::$container->invoke($type, $params);
        }

        //3. 基于配置数组创建对象
        //不是数组,就抛出异常
        if (!is_array($type)) {
            throw new InvalidConfigException('Unsupported configuration type: ' . gettype($type));
        }

        if (isset($type['__class'])) {
            $class = $type['__class'];
            unset($type['__class'], $type['class']);
            return static::$container->get($class, $params, $type);
        }

        if (isset($type['class'])) {
            $class = $type['class'];
            unset($type['class']);
            return static::$container->get($class, $params, $type);
        }

        throw new InvalidConfigException('Object configuration must be an array containing a "class" or "__class" element.');
    }

 3. 日志相关函数

// Yii日志实例
    private static $_logger;

    /**
     * 返回日志实例
     * createObject方法根据类名称创建日志对象
     * @return Logger
     */
    public static function getLogger()
    {
        if (self::$_logger !== null) {
            return self::$_logger;
        }

        return self::$_logger = static::createObject('yii\log\Logger');
    }

    /**
     * 设置日志对象
     */
    public static function setLogger($logger)
    {
        self::$_logger = $logger;
    }

    /**
     * 调试日志
     */
    public static function debug($message, $category = 'application')
    {
        if (YII_DEBUG) {
            static::getLogger()->log($message, Logger::LEVEL_TRACE, $category);
        }
    }

    /**
     * 调试日志
     */
    public static function trace($message, $category = 'application')
    {
        static::debug($message, $category);
    }

    /**
     * 错误日志
     */
    public static function error($message, $category = 'application')
    {
        static::getLogger()->log($message, Logger::LEVEL_ERROR, $category);
    }

    /**
     * 警告日志
     */
    public static function warning($message, $category = 'application')
    {
        static::getLogger()->log($message, Logger::LEVEL_WARNING, $category);
    }

    /**
     * 信息日志
     */
    public static function info($message, $category = 'application')
    {
        static::getLogger()->log($message, Logger::LEVEL_INFO, $category);
    }

    /**
     * 可以用来分析代码的性能
     * beginProfile
     * endProfile
     * 两者结合使用
     */
    public static function beginProfile($token, $category = 'application')
    {
        static::getLogger()->log($token, Logger::LEVEL_PROFILE_BEGIN, $category);
    }
    public static function endProfile($token, $category = 'application')
    {
        static::getLogger()->log($token, Logger::LEVEL_PROFILE_END, $category);
    }

 4. 多语言转换

    /**
     * powered
     */
    public static function powered()
    {
        return \Yii::t('yii', 'Powered by {yii}', [
            'yii' => '<a href="http://www.yiiframework.com/" rel="external">' . \Yii::t('yii',
                    'Yii Framework') . '</a>',
        ]);
    }

    /**
     * 多语言
     * 将消息翻译为指定的语言。
     */
    public static function t($category, $message, $params = [], $language = null)
    {
        if (static::$app !== null) {
            return static::$app->getI18n()->translate($category, $message, $params, $language ?: static::$app->language);
        }

        $placeholders = [];
        foreach ((array) $params as $name => $value) {
            $placeholders['{' . $name . '}'] = $value;
        }

        return ($placeholders === []) ? $message : strtr($message, $placeholders);
    }

5. 对象属性相关


    /**
     * 给对象挂载相关属性
     */
    public static function configure($object, $properties)
    {
        foreach ($properties as $name => $value) {
            $object->$name = $value;
        }

        return $object;
    }

    /**
     * 返回给定对象的属性
     */
    public static function getObjectVars($object)
    {
        return get_object_vars($object);
    }

总结:BaseYii.php文件做了两件事

1. 定义了一些常量

2.类中提供了很多常用的方法

本节重点:

  • 阅读了 Yii框架提供的自动加载方法 autoload
  • 阅读了createObject方法实现
  • 阅读了日志相关方法 getLogger,setLogger,debug,trace,error,warning,info,beginProfile,endProfile
  • 阅读了多语言相关方法powered, t
  • 阅读了对象属性相关方法 configure, getObjectVars

扩展学习

 1. include和require的区别

参考:PHP中include和require的区别详解_Gump的博客-CSDN博客_php require和include区别

  • PHP 系统在加载PHP程序时有一个伪编译过程,可使程序运行速度加快。但 incluce 的文档仍为解释执行。include 的文件中出错了,主程序继续往下执行,require 的文件出错了,主程序也停了 
  • require() 和 include() 语句是语言结构,不是真正的函数,可以像 php 中其他的语言结构一样,例如 echo() 可以使用 echo("ab") 形式,也可以使用 echo "abc" 形式输出字符串 abc。require() 和i nclude() 语句也可以不加圆括号而直接加参数。
  • include_once() 和 require_once() 语句也是在脚本执行期间包括运行指定文件。此行为和 include() 语句及 require() 类似,使用方法也一样。唯一区别是如果该文件中的代码已经被包括了,则不会再次包括。

2. strtr函数,转换指定字符

此函数有两种调用方式

  • strtr($str, $from,$to)
  • strtr($str, $arr)

 注意看以下两种方式的区别

<?php

$str = 'book';

//注意看,两种调用方式,结果的区别

//将 o替换成r, 将k替换成e, 所以结果是 brre
var_dump(strtr($str, 'ok', 're'));

//将ok替换成re,所以结果是bore
var_dump(strtr($str, ['ok' => 're']));

3. get_object_vars函数,获取给定对象的属性

  • 类外面调用只有 公开的非静态属性会返回
  • 类里面调用私有的,保护的,和公开的非静态属性
<?php

class Person{

    public $name;
    protected $sex;
    private $age;
    public static $addr = 'addr';

    public function __construct($name, $sex, $age)
    {
        $this->name = $name;
        $this->sex = $sex;
        $this->age = $age;
    }

    public function getObjectVars(){
        return get_object_vars($this);
    }
}

$p = new Person('Lily', 'female', 18);

// 类外面调用只有 公开的非静态属性会返回
// 结果是array(1) {'name' =>string(4) "Lily"}
var_dump(get_object_vars($p));

// 类里面调用私有的,保护的,和公开的非静态属性
// 结果是array(3) {'name' =>string(4) "Lily"  'sex' => string(6) "female"  'age' => int(18)}
var_dump($p->getObjectVars());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值