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