1. 程式人生 > 實用技巧 >ThinkPHP6 原始碼分析之解析 Request

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 釋出