ThinkPHP框架所使用的特性fastcgi_finish_request和trait
「本文會對控制器最後的執行流程和使用的兩個高階屬性進行簡單的學習,一個是fastcgi_finish_request方法巧用,另一個是trait特性,超類別的概念多少都有過了解,接下來一起來解析一下。
」
#一、如何輸出資料到終端機
當執行完控制器中的方法回應資料給App類別的run方法,直到這裡就已經執行了。
是不是有點懵這裡的資料最後會回傳哪裡呢!
之前寫過的框架執行流程、路由、控制器實例化都是從這裡開始進入的。
所以當run方法執行完成之後,就會把對應的結果給回到這裡。
這部分的程式碼Container::get('app')
應該都知道了是傳回App類別的實例。
然後透過App類別去執行run方法,才會有之前講過的一切。
下圖是喀喀爾從半中腰做的一個心智圖,前面的沒有,後邊的所有知識點都會寫在這個心智圖裡。
執行完run方法就會去執行Container::get('app')- >run()->send()
send這個方法,有多少人會認為在App類別裡邊執行send方法。
其實不是的,回想一下之前執行控制器方法然後回傳的回應結果是什麼?
如果你不是很粗略的看都會記得是Response的一個物件實例。
所以說send方法會去response類別裡邊去執行。
#先不看其它的,先看這行程式碼$this-> ;app['hook']
,現在知道是執行的那裡嗎?
這種形式就是透過存取陣列形式去存取物件的屬性,也就是先前解析的ArrayAccess這個類別。當存取的屬性不存在時會去執行offsetGet,然後執行魔術方法__get,最終透過make方法傳回實例,這一切的操作都是在容器中。
對這行程式碼具體是監聽的什麼就不去做解析了。
接著需要看處理輸出資料的這行程式碼$data = $this->getContent();
這個方法做的事情就是將傳過來的資料賦值給本類的content屬性。
其實在取得輸出資料這個方法中,請看喀喀著喀嚓圈出來的第一個地方感覺是很沒有必要。
可以看到根本對資料就沒有任何的處理,只是簡單的回傳了,所以說框架有好的地方也有不好的地方,只有你去閱讀了才會知道,否則你會對你經常使用的工具一無所知。
在接著就是Trace偵錯注入,就是透過設定檔配置的,透過呼叫debug類別來實現的,這裡就不詳解了。
然後就是快取判斷,快取會在後文中單獨拎出來講,所以也是過。
在接下來就對回應頭的設定了,偵測 HTTP 頭是否已經發送,這塊的東西就很重要了,也是平時接觸不多的知識點了。
headers_sent() :偵測HTTP 頭是否已傳送 http_response_code() :取得/設定回應的HTTP 狀態碼 #header : 函數向客戶端發送原始的HTTP 標頭。
最後一步,來了來了,它來了,它帶著echo來了,執行了一個方法$this->sendData($data);
給人一種媳婦熬成娘的感覺,終於來到的終點站,一個echo輸出了咔咔幾十天的心酸啊!
為了到達這個echo咔咔是經歷九九八十一難啊!戰鬥還未停止,同志仍需努力!
那麼到這裡關於框架執行然後到應用初始化,在到路由偵測、控制器的實例化、然後傳回response實例,在透過入口檔案執行send方法。
最後將資料輸出到終端,也就是一個echo的事情。
雖然這裡的戰鬥結束了,但是在下面還有一個非常重要的知識點,咔咔將重新提一節來進行說明。
二、fastcgi_finish_request方法巧用
在上一節中透過Container::get('app')-> ;run()->send();
在response類別中執行了send方法,輸出了資料。
但是在輸出資料之後也執行了一個方法fastcgi_finish_request();
,給的註解是提高頁面回應,接下來好好來扒一扒其中的奧秘。
在PHP官網看到這樣一段話
The script will still occupy a FPM process after fastcgi_finish_request(). So using it excessively for long running tasks may occupy all your toPM th pm.max_children. This will lead to gateway errors on the webserver.
在fastcgi_finish_request()之後,腳本仍將佔用FPM進程。因此,對於長時間運行的任務過度使用它可能會佔用您的所有FPM線程,直到pm.max_children。這將導致Web伺服器上的網關錯誤。
所以說在沒有徹底的了解這個方法之前不要輕易的在自己的專案中使用這個方法。
接下來咔咔將使用一個案例來演示這個方法的使用,僅僅只是演示使用,如果需要使用到專案中請仔細閱讀文檔應該注意的問題。
案例示範
公司有一個業務需要發送通知給用戶,但是由於發送時間太久,非常費時間,有可能需要好幾十秒的時間,更嚴重的會直接導致瀏覽器連線逾時。
在一個問題就是使用者體驗的問題,使用者等待時間過程,體驗當然不好。
為了解決以上兩個問題,今天談論的fastcgi_finish_request
就派上了用場。
理解
#對這個函數的理解其實就是發送回應給瀏覽器,使用者等待時間大大縮短,但是PHP進程還是在運作的。
這樣就達到了來個目的,就類似於我們常說的非同步執行。
直覺的來說就是發送郵件有可能需要10秒,但是用戶是沒有感知的,用戶點擊發送郵件之後直接就返回發送成功,瀏覽器響應結束,用戶做其它事情,後台進程繼續執行發送郵件的任務。
案例
<span style="display: block; background: url(" https: no-repeat rgb height: width: margin-bottom: border-radius:></span><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgb(171, 178, 191); display: -webkit-box; font-family: " operator mono consolas monaco menlo monospace font-size: background: rgb border-radius:><span class="hljs-meta" style="color: rgb(97, 174, 238); line-height: 26px;"><?php </span><br><span class="hljs-comment" style="color: rgb(92, 99, 112); font-style: italic; line-height: 26px;">/**<br> * 设置超时时间,变成不限制<br> *<br> */</span><br>set_time_limit(<span class="hljs-number" style="color: rgb(209, 154, 102); line-height: 26px;">0</span>);<br><br><span class="hljs-comment" style="color: rgb(92, 99, 112); font-style: italic; line-height: 26px;">/**<br> * 本函数模拟非常耗时的任务,执行完毕需要5秒的时间<br> */</span><br><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgb(198, 120, 221); line-height: 26px;">function</span> <span class="hljs-title" style="color: rgb(97, 174, 238); line-height: 26px;">writeFile</span><span class="hljs-params" style="line-height: 26px;">()</span><br></span>{<br> $path = <span class="hljs-string" style="color: rgb(152, 195, 121); line-height: 26px;">'D:/phpstudy_pro/WWW/kaka.txt'</span>;<br> file_put_contents($path,<span class="hljs-string" style="color: rgb(152, 195, 121); line-height: 26px;">'程序运行开始'</span> . PHP_EOL,FILE_APPEND);<br> <span class="hljs-keyword" style="color: rgb(198, 120, 221); line-height: 26px;">for</span>($i =<span class="hljs-number" style="color: rgb(209, 154, 102); line-height: 26px;">0</span>;$i 5</span>;$i++) {<br> file_put_contents($path,time() . PHP_EOL,FILE_APPEND);<br> sleep(<span class="hljs-number" style="color: rgb(209, 154, 102); line-height: 26px;">1</span>);<br> }<br><br> file_put_contents($path,<span class="hljs-string" style="color: rgb(152, 195, 121); line-height: 26px;">'程序运行结束'</span> . PHP_EOL,FILE_APPEND);<br><br>}<br><br><span class="hljs-comment" style="color: rgb(92, 99, 112); font-style: italic; line-height: 26px;">/**<br> * 输出文字标记,任务开始<br> */</span><br><span class="hljs-keyword" style="color: rgb(198, 120, 221); line-height: 26px;">echo</span>(<span class="hljs-string" style="color: rgb(152, 195, 121); line-height: 26px;">'任务开始'</span>);<br><br><span class="hljs-comment" style="color: rgb(92, 99, 112); font-style: italic; line-height: 26px;">/**<br> * 后台执行非常耗时的任务<br> */</span><br>register_shutdown_function(writeFile);<br><br><span class="hljs-comment" style="color: rgb(92, 99, 112); font-style: italic; line-height: 26px;">/**<br> * 立即发送请求<br> */</span><br>fastcgi_finish_request();<br><br><br><br></code>
以上測試全部使用linux系統進行測試哈,否則你看不到直覺的效果。
經過上面的演示,回應非常快,瀏覽器回應結束後,後台程式依然進行執行每秒執行一個時間戳。
以上就是對fastcgi_finish_request
方法的簡單介紹,如果你也感興趣可以進行簡單的嘗試一下,有助於更好的去理解其中的小秘密。
三、trait特性講解
#應該在兩個年前咔咔就對這個特性進行過一次解析,trait
就是常說的超類。
這個特性是在PHP5.4才加入的,這個特性不是常用的介面更不是類別。
這個特性是為了解決PHP的一大弱點只能單繼承的缺點,但是也不能叫多繼承,嚴謹一點的就是類似多繼承的功能而已。
接下來要為大家示範一個案例。
建立test檔一,並且傳回對應類別名稱。
建立test1文件,並且傳回對應類別名稱
建立控制器檔案用來輸出資訊。
然後在控制器中引入對應的超類別文件,這裡需要注意的是圈住的第一個框,這個框就是直接引入超類別test檔。
然後可以直接進行訪問,看看會回傳什麼。
透過上圖存取結果結果可以看得到傳回的是Test超類別檔案的方法,但是此控制器同樣也基礎了Controller控制器,也就是在文章開頭就說的超類別就是實作了一種多繼承的功能而已。
但是這裡會存在一個問題,請看下圖報錯資訊。
上圖的報錯訊息是因為在控制器中使用了兩個超類別導致的,也就是下圖的使用方式。
那麼如何解決這種報錯訊息呢!接下來跟這喀喀的節奏一起來。
解決報錯訊息
在解決之前問題之前得先清楚這個問題是由於什麼造成的。
出現這個錯誤的原因是引用的兩個trait裡面有同名的hello函數,出現了衝突。
但是在日常開發中這種情況都是可以避免的,因為手動改方法名還是很方便的,但是這裡咔咔教大家如何解決這種問題。
一是用其中一個trait裡的hello方法覆蓋另外一個trait的同名方法,因為兩個方法內容是一致的,所以我在這裡直接選擇insteadof覆蓋;
二是給他們用as取別名,這樣就不會有衝突了。 as關鍵字還有另一個用途,那就是修改方法的存取控制。
#經過上圖的改動之後,再一次的進行訪問,看一下返回結果。
那麼這個時候就會有夥伴有疑問了,就是案例列印結果一直是Test類別的方法,Test1類別的方法一直沒有進行列印。
那是如何進行訪問的呢!來接著看一下。
#從上圖可以看到將存取方法改為別名控制訪問,接著來看一下訪問結果。
#從上圖可以看到回傳結果就是超類別Test1類別的回傳結果。
那麼關於as這個的使用就需要大家在去搜尋一下使用方式,有時候注意一下細節就可以學到很多知識點。
總結
直到這裡關於控制器的原始碼解析就到這了,喀喀爾透過原始碼給大家分析控制器的如如何進行實例化的。
也再一次的進行了對ArrayAccess和魔術方法的呼叫關係,一定要有自己的思考去想問題。
在就是對存取控制器後是如何進行回應資料的,等等。
也在原始碼中學到了關於fastcgi_finish_request方法巧用,但在使用這個函數一定要注意關於喀喀爾提到的兩個注意點。
最後就是對超類別的一個簡單案例描述。
「堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在偌大互聯網中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。
”
以上是ThinkPHP框架所使用的特性fastcgi_finish_request和trait的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

執行 ThinkPHP 專案需要:安裝 Composer;使用 Composer 建立專案;進入專案目錄,執行 php bin/console serve;造訪 http://localhost:8000 查看歡迎頁面。

ThinkPHP 擁有多個版本,針對不同 PHP 版本而設計。主要版本包括 3.2、5.0、5.1 和 6.0,而次要版本用於修復 bug 和提供新功能。目前最新穩定版本為 ThinkPHP 6.0.16。在選擇版本時,需考慮 PHP 版本、功能需求和社群支援。建議使用最新穩定版本以獲得最佳性能和支援。

ThinkPHP Framework 的本機運作步驟:下載並解壓縮 ThinkPHP Framework 到本機目錄。建立虛擬主機(可選),指向 ThinkPHP 根目錄。配置資料庫連線參數。啟動 Web 伺服器。初始化 ThinkPHP 應用程式。存取 ThinkPHP 應用程式 URL 運行。

Laravel 和 ThinkPHP 框架的效能比較:ThinkPHP 效能通常優於 Laravel,專注於最佳化和快取。 Laravel 性能良好,但對於複雜應用程序,ThinkPHP 可能更適合。

《開發建議:如何利用ThinkPHP框架實現非同步任務》隨著網路技術的快速發展,Web應用程式對於處理大量並發請求和複雜業務邏輯的需求也越來越高。為了提高系統的效能和使用者體驗,開發人員常常會考慮利用非同步任務來執行一些耗時操作,例如發送郵件、處理文件上傳、產生報表等。在PHP領域,ThinkPHP框架作為一個流行的開發框架,提供了一些便捷的方式來實現非同步任務。

ThinkPHP 安裝步驟:準備 PHP、Composer、MySQL 環境。使用 Composer 建立專案。安裝 ThinkPHP 框架及相依性。配置資料庫連線。產生應用程式碼。啟動應用程式並造訪 http://localhost:8000。

ThinkPHP 是一款高效能的 PHP 框架,具備快取機制、程式碼最佳化、平行處理和資料庫最佳化等優勢。官方性能測試顯示,它每秒可處理超過 10,000 個請求,實際應用中被廣泛用於京東商城、攜程網等大型網站和企業系統。

開發建議:如何利用ThinkPHP框架進行API開發隨著網際網路的不斷發展,API(ApplicationProgrammingInterface)的重要性也日益凸顯。 API是不同應用程式之間進行通訊的橋樑,它可以實現資料共享、功能呼叫等操作,為開發者提供了相對簡單且快速的開發方式。而ThinkPHP框架作為一款優秀的PHP開發框架,具有高效能、可擴展且易用
