首頁 > 後端開發 > php教程 > 從請求到響應:前往Drupal 8內部的旅程

從請求到響應:前往Drupal 8內部的旅程

Jennifer Aniston
發布: 2025-02-17 11:11:38
原創
1015 人瀏覽過

深入Drupal 8(和Symfony2)內部:請求到響應的流程

核心要點

  • Drupal 8 利用Symfony2 的HTTPKernel 和HTTPFoundation 組件來處理用戶請求和響應,以面向對象的方式封裝請求、將其傳遞給應用程序並返迴響應。
  • HTTPKernel 組件是任何基於Symfony 的應用程序的核心,它在index.php 文件中啟動流程,並利用由事件驅動的流程。這使得應用程序更靈活,任務可以委託給這些事件的監聽器。
  • 如果控制器沒有返回Response 對象,內核會觸發kernel.view 事件,訂閱者負責將控制器的結果轉換為實際的Response 對象。這種靈活性允許控制器返回任何類型的對象,只要它與將對象轉換為正確Response 的VIEW 事件訂閱者相結合。
  • HTMLRenderer 作為最常用的主內容渲染器類型,使用頁面變體的概念構建頁面。此過程發生在HTMLRenderer 的prepare() 方法中,該方法為renderResponse() 方法提供一個#type => 'page' 渲染數組,該數組包裝了主內容。然後將其包裝到#type => 'html' 渲染數組中,並使用Renderer 類進行渲染。

在關於Drupal 8 模塊開發的第一篇文章中,我們稍微了解了此過程的路由方面。我們已經看到,創建帶有路徑的頁面現在只是聲明與控制器匹配的路由的問題。正如我們所看到的,後者可以返回一個渲染數組,該數組被解釋為標記並在該頁面的主要內容區域中顯示。但是,您是否知道,在幕後,Drupal 實際上根據Symfony 的HTTPKernelInterface 的規定將該數組轉換為Response 對象?

From Request to Response: A Journey into Drupal 8 Internals

在本文中,我想讓我們更深入地了解Drupal 8(和Symfony2)的內部結構,並了解從用戶發出請求到他們看到返回的響應的時刻之間實際發生的事情(以及可能發生的事情)。我上面提到的示例只是此過程可以進行的一個方向,今天我們還將看到其他可能性。目標是了解系統的靈活性,這反過來可以幫助我們構建出色的應用程序。

在深入研究之前,我強烈建議您查看此圖表,它在綜合通常被稱為渲染管道的內容方面做得非常出色。儘管在我看來,它代表的內容比名稱所暗示的更多,因為渲染系統只是圖中所描繪的一部分,儘管是一大部分。

前端控制器 (index.php)

Symfony2 現在是Drupal 的重要組成部分,這已不是什麼秘密。後者使用了許多Symfony 的組件,對本文而言最重要的組件是HTTPKernel 和HTTPFoundation 組件。它們共同負責封裝用戶請求,將其傳遞給應用程序,然後以一致且面向對象的方式將返回的內容返回給用戶。

HTTPKernelInterface(您可能也從其他上下文中聽說過)通過接收Request 對象並始終返回Response 對象來將所有這些粘合在一起。一個非常簡單但功能強大的概念。

此過程在index.php 文件內部啟動,該文件首先生成所述Request 對象並將其傳遞給HTTPKernel::handle() 方法。然後,後者負責返回Response 對象。從高層次來看,這在Drupal 應用程序和Symfony 應用程序(或任何其他利用HTTPKernel 組件的應用程序)中都會發生。

HTTPKernel 和事件

HTTPKernel 是任何基於Symfony 的應用程序的核心。正如我們所看到的,它的handle() 方法在準備響應方面負有很大的責任,並且它以由事件驅動的流程來做到這一點。這使得應用程序非常靈活,繁重的工作總是委託給這些事件的監聽器。

如果您查看之前的圖表,您可以看到此工作流程在第二列中進行了描述,它基本上代表了Symfony 和Drupal 方面的粘合劑。

它從第一個名為kernel.request 的事件開始。此事件的訂閱者處理各種任務。但在Drupal 8 中,兩個非常重要的任務是格式協商和路由。第一個確定需要返回的響應類型(html、json、圖像、pdf 等),第二個確定負責處理此響應的代碼(routing.yml 文件內路由定義的_controller 密鑰)。但是,就像此事件工作流程中的大多數步驟一樣,如果偵聽器返回response 對象,則該過程會跳過大部分後續步驟(停止傳播)並直接轉到kernel.response。

第二個事件是kernel.controller,它在應用程序知道哪個控制器負責處理請求後被調用。此時,偵聽器仍然可以對其執行一些覆蓋操作。緊隨此步驟之後,內核負責解析傳遞給控制器的參數。 Drupal 中的一個這樣的操作是根據請求中找到的ID(例如節點)加載對象,並直接向控制器提供這些對象。然後,控制器最終會使用相應的參數被調用。

控制器負責返回某種響應。如果它返回Response 對象,則該過程會跳到kernel.response 事件。後者的偵聽器可以對對象執行最後一分鐘的修改,例如修改標頭或內容本身。並且在從handle() 方法獲取它之後,前端控制器使用Response 對像上的send() 方法將其發送回用戶並終止該過程。

From Request to Response: A Journey into Drupal 8 Internals

更深入地了解渲染數組

如果控制器沒有返回Response 對象,則內核會觸發最後一個事件:kernel.view。它的訂閱者負責將控制器的結果轉換為實際的Response 對象。因此,這意味著您可以從控制器返回任何類型的對象,只要您將其與將該對象轉換為正確的Response 的VIEW 事件訂閱者相結合即可。

但是,正如我們在示例中看到的,控制器大多數時候會返回渲染數組。這通常表示頁面的主要內容(類似於Drupal 7 中的頁面回調)。

為了處理這個問題,Drupal 8 有一個MainContentViewSubscriber 負責將此數組轉換為正確的Response 對象。它通過使用在前面討論過的格式協商階段選擇的特定MainContentRenderer 來做到這一點。儘管已經有一些這樣的渲染器可用,但使用的默認渲染器是HtmlRenderer。

HTMLRenderer

由於這是最常用的主內容渲染器類型,因此讓我們更深入地了解一下它是如何構建頁面的。

此過程中的一個很酷的事情是頁面變體的概念。這意味著HTMLRenderer 分派一個負責找出要使用哪種類型的頁面來包裝主內容渲染數組的事件:RenderEvents::SELECT_PAGE_DISPLAY_VARIANT。默認情況下,除非啟用了Block 模塊,否則使用SimplePageVariant。在這種情況下,BlockPageVariant 會啟動並允許在主要內容周圍的區域中放置塊。如果需要,您可以在自己的模塊中訂閱此事件並提供您自己的變體。

所有這些都發生在HTMLRenderer 的prepare() 方法中,該方法為renderResponse() 方法提供一個#type => 'page' 渲染數組,該數組包裝了主內容數組。後兩者依次被包裝到#type => 'html' 渲染數組中,該數組最終使用Renderer 類(Drupal 7 中drupal_render() 的等效項)進行渲染。生成的HTML 字符串將添加到Response 對像中並返回給前端控制器。

雖然這是對該過程非常高級別的概述,但這基本上就是發生的事情。現在我們有一個Response 對象,這意味著內核可以分派其kernel.response 事件。之後,前端控制器可以直接將Response 發送回用戶並終止該過程。

結論

在本文中,我們通過跟踪從用戶請求到服務器返回的響應的管道,對Drupal 8(和Symfony2)內部進行了探索。我們已經看到Drupal 8 如何利用HTTPKernel 和HTTPFoundation Symfony2 組件,以及它基本上如何位於這些組件之上。此外,我們還看到了它們之間的粘合劑是如何由內核分派的事件組成的,Drupal 為其所有功能訂閱了這些事件。最後,我們已經看到如何在渲染管道的幫助下構建並返回HTML 頁面給用戶。

我相信了解Drupal 8 應用程序中幕後發生的事情將使您能夠通過準確了解進入此流程的入口點來創建出色的應用程序。我相信,如果您只從本文中帶走一件事情,那應該是靈活性這個詞。因為在Drupal 8 中構建我們所需內容的靈活性遠遠超過Drupal 7 中的任何內容。它確實已經變得現代化了。

關於Drupal 8 內部結構的常見問題解答 (FAQ)

Drupal 7 和Drupal 8 的主要區別是什麼?

與Drupal 7 相比,Drupal 8 引入了幾個重大變化。它有一個名為Twig 的新的主題引擎,它更安全、更靈活。 Drupal 8 也更適合移動設備,並且包含更多內置字段。它更好地支持多語言站點,具有改進的語言管理和翻譯支持。此外,由於廣泛使用Symfony 組件,Drupal 8 與第三方平台的集成更好。

Drupal 8 如何處理請求和響應?

Drupal 8 使用Symfony HttpKernel 組件來處理請求和響應。當發出請求時,Drupal 8 會創建一個Request 對象並將其傳遞給HttpKernel。然後,HttpKernel 使用路由系統來確定哪個控制器應該處理該請求。控制器處理請求並返回一個Response 對象,HttpKernel 將其發送回客戶端。

路由系統在Drupal 8 中的作用是什麼?

Drupal 8 中的路由系統負責將URL 映射到特定的控制器。它使用模塊提供的路由定義來確定哪個控制器應該處理給定的請求。路由系統還支持動態路由,這些路由可以根據系統的狀態而改變。

Drupal 8 的主題系統如何工作?

Drupal 8 的主題系統使用Twig,這是一個靈活且安全的模板引擎。 Drupal 8 中的主題由一個.info.yml 文件(提供有關主題的元數據)和Twig 模板文件(定義HTML 輸出)組成。主題系統還支持模板繼承,允許主題擴展和覆蓋來自其他主題或模塊的模板。

我如何在Drupal 8 中開發自定義模塊?

在Drupal 8 中開發自定義模塊包括創建一個.info.yml 文件來提供有關模塊的元數據,以及一個.module 文件來包含模塊的PHP 代碼。模塊還可以包含其他文件,例如定義路由的路由文件和定義服務的服務文件。 Drupal 8 使用面向對象編程和Symfony 組件,使編寫可重用和可測試的代碼更容易。

使用Drupal 8 進行Web 開發的好處是什麼?

Drupal 8 為Web 開發提供了許多好處。它使用Symfony 組件使其更加強大和靈活。它開箱即用地支持響應式設計,使創建移動友好型網站更容易。 Drupal 8 還改進了多語言支持、更好的SEO 功能和更用戶友好的管理界面。

Drupal 8 如何處理數據庫交互?

Drupal 8 使用數據庫API 來處理數據庫交互。數據庫API 在SQL 之上提供了一個抽象層,允許開發人員編寫數據庫查詢而無需了解底層數據庫引擎的細節。它還支持動態查詢、事務和模式管理。

事件調度程序在Drupal 8 中的作用是什麼?

Drupal 8 中的事件調度程序用於管理事件和事件偵聽器。當發生事件時,事件調度程序會通知所有已註冊的偵聽器,然後這些偵聽器可以採取行動。這允許模塊以解耦的方式相互交互。

Drupal 8 如何處理緩存?

Drupal 8 具有一個複雜的緩存系統,有助於提高性能。它支持多個緩存後端,包括基於數據庫、文件和內存的後端。 Drupal 8 還具有緩存標記系統,允許對緩存數據進行細粒度的失效。

我如何擴展Drupal 8 的功能?

Drupal 8 的功能可以通過模塊和主題來擴展。模塊添加新功能或修改現有功能,而主題控制站點的外觀和感覺。 Drupal 8 還支持插件,允許交換功能部件,以及服務,提供可重用的功能,可以注入到系統的其他部分。

This revised output maintains the original meaning while rephrasing sentences and paragraphs, avoiding direct copying. The image URLs are preserved. The formatting is adjusted for better readability.

以上是從請求到響應:前往Drupal 8內部的旅程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板