写在前面,写这些随笔是记录下自己看Yii2源码的过程,可能会有些流水账,大部分解析放在注释里说明,由于个人水平有限,有不正确的地方还望斧正。

web入口文件Index.php

  1. // 定义全局的常量,YII_DEBUG标识是够开启debug模式,YII_ENV标识出当前运行环境,默认env(开发), 上线后改成prod来表示正式环境。
  2. defined('YII_DEBUG') or define('YII_DEBUG', true);
  3.  
  4. defined('YII_ENV') or define('YII_ENV', 'dev');
  5.  
  6. // 加载composer vendor的autoload文件
  7. require(__DIR__ . '/../vendor/autoload.php');
  8. // 加载Yii框架
  9. require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

入口文件很简单,做了一些初始化工作,具体看注释。

接下来看加载的Yii文件代码:

  1. <?php
  2. /**
  3. * Yii bootstrap file.
  4. *
  5. * @link http://www.yiiframework.com/
  6. * @copyright Copyright (c) 2008 Yii Software LLC
  7. * @license http://www.yiiframework.com/license/
  8. */
  9.  
  10. require(__DIR__ . '/BaseYii.php');
  11.  
  12. /**
  13. * Yii is a helper class serving common framework functionalities.
  14. *
  15. * It extends from [[\yii\BaseYii]] which provides the actual implementation.
  16. * By writing your own Yii class, you can customize some functionalities of [[\yii\BaseYii]].
  17. *
  18. * @author Qiang Xue <qiang.xue@gmail.com>
  19. * @since 2.0
  20. */
  21. class Yii extends \yii\BaseYii
  22. {
  23. }
  24. // 调用Yii::autoload来注册autoload, 而且是放到autoload队列之首。
  25. spl_autoload_register(['Yii', 'autoload'], true, true);
  26. // 包含class映射文件
  27. Yii::$classMap = require(__DIR__ . '/classes.php');
  28. // 初始化DI容器
  29. Yii::$container = new yii\di\Container();

PS:这边涉及到php的自动加载概念(https://www.php.net/manual/zh/function.spl-autoload-register)和设计模式-依赖注入。

这个文件主要进行一些YII源码的初始化操作,这里的class Yii只是继承了BaseYii,没有写任何代码,所以yii2的源码都是在BaseYii里面的,这里留空是为了给使用者自定义的。

注册自动加载

  1. public static function autoload($className)
  2. {
  3. // 从classMap里寻找
  4. if (isset(static::$classMap[$className])) {
  5. $classFile = static::$classMap[$className];
  6. if ($classFile[0] === '@') {
  7. $classFile = static::getAlias($classFile);
  8. }
  9. } elseif (strpos($className, '\\') !== false) {
  10. // 命名空间访问,先把命名空间的格式转成路径别名,例如: yii\base\Component 转成 @yii/base/Component.php
  11. $classFile = static::getAlias('@' . str_replace('\\', '/', $className) . '.php', false);
  12. if ($classFile === false || !is_file($classFile)) {
  13. return;
  14. }
  15. } else {
  16. return;
  17. }
  18.  
  19. include($classFile);
  20.  
  21. if (YII_DEBUG && !class_exists($className, false) && !interface_exists($className, false) && !trait_exists($className, false)) {
  22. throw new UnknownClassException("Unable to find '$className' in file: $classFile. Namespace missing?");
  23. }
  24. }

​ 简单总结下,这个函数规定了一些规则让php在寻找未知class时候可以include对应的文件,规则如下:

​ (1) 在classMap里面找

​ (2)如果class是使用命名空间访问的(例如:yii\base\Component), 会按照@yii/base/Component.php这样的路径去加载。

规则1

规则1说从classMap里面,那么classMap是什么呢,在入口文件里能找到Yii::$classMap = require(__DIR__ . '/classes.php');,然后去看下classes.php是什么样子的:

  1. return [
  2. 'yii\base\Action' => YII2_PATH . '/base/Action.php',
  3. 'yii\base\ActionEvent' => YII2_PATH . '/base/ActionEvent.php',
  4. .....
  5. ]

只是返回一个数组,key是class的名字,value是对应php文件的路径(YII2_PATH是预定于的常量,表示当前目录)。

if (isset(static::$classMap[$className])) {

所以Yii::autoload会先判断是否在classMap里面。

规则2(命名空间)

  1. $classFile = static::getAlias('@' . str_replace('\\', '/', $className) . '.php', false);

函数会先把命名空间形式的调用转成对应的路径别名,再用getAlias函数转成对应的路径。

路径别名

再来看看static::getAlias()这个函数是怎么把路径别名转成路径的。

  1. public static $aliases = ['@yii' => __DIR__]; // 预设的路径别名映射数组
  1. public static function getAlias($alias, $throwException = true)
  2. {
  3. // 检查是否有@前缀,没有的话直接返回。
  4. if (strncmp($alias, '@', 1)) {
  5. // not an alias
  6. return $alias;
  7. }
  8. // 取出@alias部分赋值给root
  9. $pos = strpos($alias, '/');
  10. $root = $pos === false ? $alias : substr($alias, 0, $pos);
  11. // 检查root是否在$aliases里是否有对应的alias
  12. if (isset(static::$aliases[$root])) {
  13. // 在$aliases里找到对应的@alias然后转化成实际的路径并返回
  14. if (is_string(static::$aliases[$root])) {
  15. return $pos === false ? static::$aliases[$root] : static::$aliases[$root] . substr($alias, $pos);
  16. }
  17. // 如果找到的不是对应的路径字符串,就变量这个数组,看看里面有没有对应的
  18. foreach (static::$aliases[$root] as $name => $path) {
  19. if (strpos($alias . '/', $name . '/') === 0) {
  20. return $path . substr($alias, strlen($name));
  21. }
  22. }
  23. }
  24.  
  25. if ($throwException) {
  26. throw new InvalidParamException("Invalid path alias: $alias");
  27. }
  28.  
  29. return false;
  30. }

创建Web应用实例

  1. $config = require(__DIR__ . '/../config/web.php'); // 加载配置文件
  2. (new yii\web\Application($config))->run();

到这里就开始涉及config配置的解析了,下一篇才慢慢分析。

Yii2源码分析(一):入口的更多相关文章

  1. Yii2 源码分析 入口文件执行流程

    Yii2 源码分析  入口文件执行流程 1. 入口文件:web/index.php,第12行.(new yii\web\Application($config)->run()) 入口文件主要做4 ...

  2. CodeIgniter框架——源码分析之入口文件index.php

    CodeIgniter框架的入口文件主要是配置开发环境,定义目录常量,加载CI的核心类core/CodeIgniter.php.   在index.php中,CI首先做的事情就是设置PHP的错误报告, ...

  3. jQuery 源码分析(二) 入口模块

    jQuery返回的对象本质上是一个JavaScript对象,而入口模块则可以保存对应的节点的引用,然后供其它模块操作 我们创建jQuery对象时可以给jQuery传递各种不同的选择器,如下: fals ...

  4. twemproxy源码分析1——入口函数及启动过程

    最近工作中需要写一个一致性哈希的代理,在网上找到了twemproxy,结合网上资料先学习一下源码. 一.Twemproxy简介 Twemproxy是memcache与redis的代理,由twitter ...

  5. yii2 源码分析1从入口开始

    我是在 backend 一步步打印的 很多地方我也是很模糊 .后来发现一位大神的文章(http://www.yiichina.com/tutorial/773) 参考文章自己动手开始写的 至于后来的 ...

  6. yii2 源码分析 object类分析 (一)

    转载请注明链接http://www.cnblogs.com/liuwanqiu/p/6737327.html yii2基本上所有的类都是继承的object类,下面就来分析一下object类吧 obje ...

  7. yii2 源码分析 model类分析 (五)

    模型类是数据模型的基类.此类继承了组件类,实现了3个接口 先介绍一下模型类前面的大量注释说了什么: * 模型类是数据模型的基类.此类继承了组件类,实现了3个接口 * 实现了IteratorAggreg ...

  8. yii2 源码分析Action类分析 (六)

    Action类是控制器的基类, <?php namespace yii\base; use Yii; /** * Action是所有控制器动作类的基类,它继承组件类 * * 动作提供了重用动作方 ...

  9. yii2 源码分析Behavior类分析 (四)

    Behavior类是所有事件类的基类,它继承自object类 Behavior类的前面注释描述大概意思: * Behavior类是所有事件类的基类 * * 一个行为可以用来增强现有组件的功能,而不需要 ...

随机推荐

  1. AWS 创建redis 集群模式遇到的问题

    问题描述 前几天在aws 平台创建了Redis 集群模式,但是链接集群的时候发现无法连接,返回信息超时. 通过参数组创建redis的时候提示报错:Replication group with spec ...

  2. SignalR控制台自托管服务端向web客户端指定用户推送数据,客户端断线重连

    一.前言 SignalR是微软推出的开源实时通信框架.其内部使用Web Socket, Server Sent Events 和 Long Polling作为底层传输方式,SignalR会根据客户端和 ...

  3. UniRx精讲(一):UniRx简介&定时功能实现

    1.UniRx 简介 UniRx 是一个 Unity3D 的编程框架.它专注于解决时间上异步的逻辑,使得异步逻辑的实现更加简洁和优雅. 简洁优雅如何体现? 比如,实现一个"只处理第一次鼠标点 ...

  4. Flask flush 闪现

    闪现 要用必须导入 flash , get_flashed_messages flash 用于存闪现的值.他有两个参数,1 messsage,用来存储信息 2 category ,用于给信息分类,该参 ...

  5. JSP和Servlet的相同点和不同点、有何联系。

    JSP 和 Servlet 有哪些相同点和不同点,他们之间的联系是什么? 联系: JSP 是 Servlet 技术的扩展,本质上是 Servlet 的简易方式,更强调应用的外表表达. JSP编译后是& ...

  6. Nginx思维导图

    1. Nginx简介 1.1 nginx概述 1.2 nginx的安装及程序环境 1.3 零复制&五种IO模型 1.4 nginx的基本配置 2. Nginx配置详解 2.1 main配置段详 ...

  7. [ARC101B]Median of Medians

    题目   点这里看题目. 分析   看到中位数,当然会想到二分答案.   考虑检查答案.自然,我们需要找出中位数小于二分值\(k\)的区间的个数.考虑构造一个\(b\): \[b_i=(-1)^{[a ...

  8. IDEA Gradle项目控制台输出乱码

    idea 更新到2019.2.3没有这个选项. 可以点击 help->edit custom vm options 然后加上 -Dfile.encoding=utf-8 重启一下就好了

  9. ado.net Web前端:关于JavaScript知识点的简单梳理

    学习js:1.htmml2.cssjs+html+css == html5 js的组成:1).ecamscript ES是js的标准,js 是es 的实现2)文档对象模型(Document Objec ...

  10. 曹工改bug:centos下,mongodb开机不能自启动,systemctl、rc.local都试了,还是不行,要不要放弃?

    问题背景 最近装个centos 7.6的环境,其中,基础环境包括,redis.nginx.mongodb.fastdfs.mysql等,其中,自启动使用的是systemctl,其他几个组件,都没啥问题 ...