ThinkPHP6 源码分析之解析 Request

获取 Request 对像

在进入正题之前,需要重点说一下 make 方法。因为从上个版本使用过来的人已经开始接受 Container 这个概念了,这个新版本的增强了 Container 的功能,创建 Request 对象的精髓就在 make 方法。倒不如说整个框架核心类都在使用这个方法。我们来看一下这个方法是如何创建对象的。具体说明请看每一段的注释

public function make(string $abstract, array $vars = [], bool $newInstance = false)
{
    // 首先说明 instances 属性是一个数组,就是主要存储容器对象
    // 如果对象存在与容器中并且不需要重新创建的话,就直接从容器中获取
    if (isset($this->instances[$abstract]) && !$newInstance) {
        return $this->instances[$abstract];
    }
    // bind 属性从上一个应用初始化已经接触到了,
    // 就是容器对象的绑定标识,和 instances 数组不同的是,
   // 它只是存储了一个类字符串而已,需要实例化后获取对象实例,下面就是实现的该功能

    // 如果 bind 标识存在
    if (isset($this->bind[$abstract])) {
        // 从 bind 获取
        $concrete = $this->bind[$abstract];
        // concrete 可能是一个类名或者是一个匿名函数
        // 匿名函数直接执行
        if ($concrete instanceof Closure) {
            $object = $this->invokeFunction($concrete, $vars);
        } else {
            // 否则继续 make 创建,因为此时还没创建出对象
            return $this->make($concrete, $vars, $newInstance);
        }
    } else {
        // 如果没有在标识中 说明需要的类名真正的产出了,需要实例化。
        // 其实这里才是真正的创建类,并且下面的方法直接依赖注入
        $object = $this->invokeClass($abstract, $vars);
    }
    // 对于不需要创建实例的类 直接放在容器中管理
    if (!$newInstance) {
        $this->instances[$abstract] = $object;
    }
    // 最后返回对象
    return $object;
}

可能到这里看的还是有点糊涂,正好在这里用 Request 创建来梳理一下。我们来看看创建 Request 的过程。

分析

下面这段代码可以的 run 方法中找到,这段代码需要仔细推敲,不然你无法知道这个 Request 对象到底是哪个?

//自动创建request对象
$request = $request ?? $this->app->make('request', [], true);
$this->app->instance('request', $request);

$newInstance 在 Request 创建时被设置为了 true,说明每次请求都需要重新创建。此时 instances 还未有 Request 对象,所以继续忽略。 在进入 bind 之前,先看看 bind 里面都有什么了?

array(22) {
  ["app"]=>
  string(9) "think\App"
  ["cache"]=>
  string(11) "think\Cache"
  ["config"]=>
  string(12) "think\Config"
  ["console"]=>
  string(13) "think\Console"
  ["cookie"]=>
  string(12) "think\Cookie"
  ["db"]=>
  string(8) "think\Db"
  ["env"]=>
  string(9) "think\Env"
  ["event"]=>
  string(11) "think\Event"
  ["http"]=>
  string(10) "think\Http"
  ["lang"]=>
  string(10) "think\Lang"
  ["log"]=>
  string(9) "think\Log"
  ["middleware"]=>
  string(16) "think\Middleware"
  ["request"]=>
  string(13) "think\Request"
  ["response"]=>
  string(14) "think\Response"
  ["route"]=>
  string(11) "think\Route"
  ["session"]=>
  string(13) "think\Session"
  ["validate"]=>
  string(14) "think\Validate"
  ["view"]=>
  string(10) "think\View"
  ["filesystem"]=>
  string(16) "think\Filesystem"
  ["Psr\Log\LoggerInterface"]=>
  string(9) "think\Log"
  ["think\Request"]=>
  string(11) "app\Request"
  ["think\exception\Handle"]=>
  string(19) "app\ExceptionHandle"
}

默认已经有了很多类名,这些都是框架默认的,不需要管,我们只看 request 键名和 ‘think\Request‘,还有最后两个 think\Requestthink\exception\Handle 是在框架初始化注入进来的,不清楚的可以看上一节。think\Request 就是在那个时候注入的。

下面进入正题,很明显 'request' 在存在与 bind 中的,并且 request 的值并不是一个匿名函数,而是一个字符串 think\Request,只能继续 make 创建,找到 think\Request 对应的值 app\Request,它并不存在与 bind 中,所以直接来解析这个类名。这里大概就明白了,实际框架并没有在使用 think\Request 对象,而是 app\Request 对象。在解析后,Request 对象也被放进了容器了。下面就是请求的执行过程了。


更多学习内容可以访问【对标大厂】精品PHP架构师教程目录大全,只要你能看完保证薪资上升一个台阶(持续更新)

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以点击链接领取进阶PHP月薪30k>>>架构师成长路线【视频、面试文档免费获取】

本文由博客群发一文多发等运营工具平台 OpenWrite 发布

猜你喜欢

转载自blog.csdn.net/weixin_49163826/article/details/108021757