ThinkPHP路由地址是怎么進行控制器實例化的

一、執行控制器中的方法

本文的請求地址為配置的域名。

ThinkPHP路由地址是怎么進行控制器實例化的

通過上文可以知道$instance的值就是appindexcontrollerIndex的實例。

這塊也是存在中間件的概念,依然如此中間件會在后文中單獨提到,這里不做解釋。

在這里$this->app[‘middleware’]->controller這段代碼的使用,還能記得是使用的ArrayAccess還是直接為__get嗎?

這里是在使用訪問數組的形式訪問對象,所以使用的是ArrayAccess的形式,這倆種概念一定要區分清楚。

ThinkPHP路由地址是怎么進行控制器實例化的

接下來就會執行獲取方法名,至于這個方法名怎么獲取的是在本類的init方法執行的,這里只需要知道返回的是index即可。

在這里需要注意的就是這行代碼$this->rule->getConfig(‘action_suffix’),這里獲取的是操作方法后綴。

ThinkPHP路由地址是怎么進行控制器實例化的

假如現在給這個操作方法后綴設置一個值會變成什么樣子呢!

給添加一個kaka的值,進行訪問一下看會是什么結果。

ThinkPHP路由地址是怎么進行控制器實例化的

這個時候進行訪問會提示indexkaka的這個方法不存在,是不是清晰可見了,說明這個參數是在為所有的方法名追加一個kaka。

ThinkPHP路由地址是怎么進行控制器實例化的

立即學習PHP免費學習筆記(深入)”;

對獲取當前操作名的代碼進行擴展完成之后,緊接著就是if (is_callable([$instance, $action])) {,在這里可以看見我們的老朋友is_callable。

對于這里的is_callable倆個參數通過上文都知道是什么了,第一個參數為appindexcontrollerIndex的實例,第二個參數為index執行操作方法。

那么is_callable的作用就是檢測在appindexcontrollerIndex類中的index方法名是否可以執行。

很明顯這里會返回一個true,因為在index類里邊存在index方法的。

這里在做測試之前一定要把剛剛在app的配置文件中配置的方法名后綴那個給取消掉。

通過這個is_callable判斷會存在三種情況,接下來咔咔將會從三個方面給大家進行解析。

第一種情況:類里邊存在可執行的方法

  • 首先返回一個 ReflectionMethod 類
  • 獲取方法名 index
  • 未設置方法名后綴返回空
  • 設置當前的操作名
  • 在這個案例中沒有設置參數,所以最終的$vars就是一個空數組。

為了測試帶有參數的這一段代碼,我們需要對路由地址進行一點改動。

ThinkPHP路由地址是怎么進行控制器實例化的

在之前沒有使用路由,而是直接使用的默認地址,接下來將使用這個路由地址

ThinkPHP路由地址是怎么進行控制器實例化的

使用這個路由地址進行一下數據的打印,可以看到就是我們設置的路由參數。

ThinkPHP路由地址是怎么進行控制器實例化的

這段獲取請求變量的方法會進入到$this->request->param();這行代碼

框架是如何獲取參數的

訪問地址:http://www.source.com/index.php/hello/hello

在上文知道是通過$this->request->param()來獲取參數的,那么在框架是如何獲取參數的呢!

根據流程代碼會執行到下圖,根據獲取的請求方式來使用對應的方式來獲取參數,在這里需要明確的是我們使用的是get請求。

所以代碼會執行到$this->param,當前請求參數和URL地址中的參數合并這里,在這里注意咔咔圈出來的地方。

由于咔咔是使用路由方式進行的請求所以,在這里框架專門為路由封裝了一個獲取請求參數。

ThinkPHP路由地址是怎么進行控制器實例化的

來到這個route方法,看到注釋就明白是用來獲取路由參數的,但是還是需要在進入一層到input

ThinkPHP路由地址是怎么進行控制器實例化的

在之前路由的那一期文章中在獲取到路由參數的時候會把參數合并到request的route屬性。

ThinkPHP路由地址是怎么進行控制器實例化的

所以說$this->route就是存放的這條路由規則所有的參數,包含路由參數。

ThinkPHP路由地址是怎么進行控制器實例化的

這時執行流程會執行到獲取變量 支持過濾和默認值,在上文中$this->route穿進來的參數是false,所以說這塊會直接返回。

ThinkPHP路由地址是怎么進行控制器實例化的

這里返回的結果會返回給上文我們開始解析的地方,也就是說這個$vars就是獲取到的路由參數。

ThinkPHP路由地址是怎么進行控制器實例化的

第二種情況:類里邊不存在可執行的方法

當第一種判斷執行is_callable判斷類里邊的方法不可執行時,就會執行到第二種情況。

ThinkPHP路由地址是怎么進行控制器實例化的

先來請求的一個沒有設置的路由地址,看會返回什么。

ThinkPHP路由地址是怎么進行控制器實例化的

根據代碼給的提示,我們來到index控制器建立一個_empty方法,然后在來請求一次,看一下會發生什么。

ThinkPHP路由地址是怎么進行控制器實例化的

根據打印結果就可以看出來當訪問的方法不存在時就會去執行_empty這個方法。

ThinkPHP路由地址是怎么進行控制器實例化的

那么這個方法是怎么執行的呢!這種執行方式就是利用反射機制來實現的,關于反射咔咔之前專門出了一篇文章來講解的,但是大家還是需要對著文檔進行閱讀查看。

第三種情況:類里邊不存在可執行的方法也不存在_empty方法

這種情況就比較簡單了,就是直接返回錯誤信息,關于這里異常處理咔咔也會在后文說到。

ThinkPHP路由地址是怎么進行控制器實例化的

三種情況執行完

三種情況分析完了,最后都會去執行統計的方法。

調用反射執行類的方法 支持參數綁定,也就說這里的閉包執行流程到這里就執行完了。

關于后邊的自動請求,在第五節中詳細說明。

ThinkPHP路由地址是怎么進行控制器實例化的

二、路由地址是怎么進行控制器實例化的

在上一節中我們對路由進行了三四期的講解,最終講解的位置就路由調度,那么設置的路由是如何執行呢!

接下來使用這個路由作為案例

ThinkPHP路由地址是怎么進行控制器實例化的

還記得在開始進行路由檢測時的返回值是什么嗎?請看下圖

ThinkPHP路由地址是怎么進行控制器實例化的

ThinkPHP路由地址是怎么進行控制器實例化的

當時沒有對接下里的代碼進行詳解,直接說明了實例化控制器,現在要說的就是記錄當前調度信息這行代碼。

在這里$this->request是使用的當訪問不存在的屬性時會去執行容器類的魔術方法,最后通過容器返回一個實例。

所以說代碼會執行到下圖位置,設置或者獲取當前請求的調度信息

ThinkPHP路由地址是怎么進行控制器實例化的

通過在控制器實例化這里進行打印會發現在這里的返回的值是index,這個值是在控制器進行設置的,接下來來到控制器進行查看一下。

ThinkPHP路由地址是怎么進行控制器實例化的

來到init方法對result做打印查看結果,使用的是路由地址

ThinkPHP路由地址是怎么進行控制器實例化的

ThinkPHP路由地址是怎么進行控制器實例化的

ThinkPHP路由地址是怎么進行控制器實例化的

你知道到為什么這里的值發生改變了嗎?

在上文打印出來的值為下圖,為什么在這里就是上圖的呢!

ThinkPHP路由地址是怎么進行控制器實例化的

在路由那一節中最后一步就是發起路由調度,最后調用了一個路由到模塊/控制器/操作這個方法。

ThinkPHP路由地址是怎么進行控制器實例化的

這個方法dispatchModule最后也是實例化一個類,接下來需要對這個類進行深究

ThinkPHP路由地址是怎么進行控制器實例化的

根據代碼追蹤可以看到其實就是thinkroutedispatchModule這個類

ThinkPHP路由地址是怎么進行控制器實例化的

來到Module這個類,又會發現繼承著Dispatch類

ThinkPHP路由地址是怎么進行控制器實例化的

thinkphp/library/think/route/Dispatch.php這個類的控制器中,會發現對dispatch這個變量進行了設置。

ThinkPHP路由地址是怎么進行控制器實例化的

這個時候回頭在看一下路由到模塊/控制器/操作這里的方法傳入的參數是什么,哈哈

ThinkPHP路由地址是怎么進行控制器實例化的

所以說最終的值就是剛剛打印的只是單獨的數組形式的。

ThinkPHP路由地址是怎么進行控制器實例化的

那么接下來的動作就跟不使用路由訪問的流程一樣的,就不用在進行解析了。

直到這里關于路由地址是怎么進行控制器實例化的就結束了。

關于給$this->app->controller傳入的是index,返回的是整個類名,具體的實現過程就不去解析了,實現的方法是$this->parseModuleAndClass,可以自行進行研究哈!

三、執行autoResponse調度

在第四節中只提到了執行控制器中的方法是從下圖的地方進行返回的,但是怎么返回的沒有進行詳解。

接下里會用一丟丟的時間來說一下是如何執行的。

ThinkPHP路由地址是怎么進行控制器實例化的

訪問路由地址為下圖,可以看到返回的數據就是控制器中需要返回的數據。

ThinkPHP路由地址是怎么進行控制器實例化的

ThinkPHP路由地址是怎么進行控制器實例化的

打印的值是下圖地方,這里就需要明確哈!源碼閱讀就是這樣需要一點點的進行摸索,時間長了就對其中的東西就明白了。

ThinkPHP路由地址是怎么進行控制器實例化的

接下來就對$this->autoResponse($data);這個方法進行深入的解析,這個方法按照字面意思就是自動響應。

ThinkPHP路由地址是怎么進行控制器實例化的

在這個執行流程的第一行中$data instanceof Response,對這個不了解接下來就沒辦法閱讀了。

不會和不明白的還是需要去解決的,閱讀源碼就這樣,一點點的攻克才能獲得勝利。

關于instanceof的使用

instanceof可以判斷某個對象是否是某個類的實例,判斷一個對象是否實現了某個接口

接下來咔咔針對這個做一個簡單的實例給大家演示一下,就明白這個是怎么回事了。

案例一

首先建立倆個類,案例如下圖。

ThinkPHP路由地址是怎么進行控制器實例化的

下圖就是打印結果,可以看到第一個返回true,第二個返回false。

判斷某個對象是否是某個類的實例,也就是說$instance就是類Test的實例,所以會返回true。

ThinkPHP路由地址是怎么進行控制器實例化的

案例二

案例二跟案例一是不同的,建立了一個接口,然后類實現接口的案例。

ThinkPHP路由地址是怎么進行控制器實例化的

最終返回結果全是true,也就是說如果一個類實現了另一個接口,那么在判斷時都會是true。

ThinkPHP路由地址是怎么進行控制器實例化的

? 版權聲明
THE END
喜歡就支持一下吧
點贊10 分享