国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 後端開發(fā) php教程 前控制器圖案的簡介,第2部分

前控制器圖案的簡介,第2部分

Feb 26, 2025 am 09:55 AM

An Introduction to the Front Controller Pattern, Part 2

核心要點

  • 前端控制器充當應用程序的集中式代理,將命令分派給預定義的處理程序,例如頁面控制器或 REST 資源。
  • 前端控制器可以保持緊湊的結構,路由和分派傳入請求,也可以擴展為功能齊全的 RESTful 控制器,解析 HTTP 動詞,適應預/後分派鉤子等。
  • 本文演示瞭如何部署一個小型但可擴展的 HTTP 框架,該框架能夠與前端控制器、獨立路由器和調度程序一起工作,同時獨立處理請求/響應週期。
  • 作者還介紹了從頭開始構建前端控制器的過程,包括定義類來模擬典型 HTTP 請求/響應週期的數據和行為,構建路由模塊以及設置調度程序。
  • 前端控制器模式具有集中控制、減少代碼重複以及改進模塊化和關注點分離等優(yōu)點,但它可能不適用於所有 Web 應用程序,如果實現不當,可能會導致單點故障。

前端控制器就像應用程序中的集中式代理,其主要關注領域是靜態(tài)或動態(tài)地將命令分派給預定義的處理程序,例如頁面控制器、REST 資源或任何其他想到的東西。構建至少一個簡單的前端控制器是理解其細節(jié)的非常有益的經驗,為了從務實的角度推廣這一想法,我在介紹性文章中介紹了一個人為的前端控制器的實現,該控制器將路由和分派請求所需的所有邏輯打包在一個類的邊界內。前端控制器最好的方面之一是您可以將它們保持為緊湊的結構,只路由和分派傳入請求,或者您可以展現您的創(chuàng)造力,並實現一個功能齊全的RESTful 控制器,能夠解析HTTP動詞,適應預/後分派鉤子等等,所有這些都在統(tǒng)一的API 後面。但是,雖然這種方法很有吸引力,但它違反了單一職責原則 (SRP) 並違背了 OOP 本身主動將不同任務委託給多個細粒度對象的本質。那麼,這是否意味著我只是另一個膽敢違反 SRP 戒律的有罪靈魂呢?從某種意義上說,是的。因此,我想通過向您展示如何輕鬆部署一個小型但可擴展的 HTTP 框架來消除我的罪惡,該框架能夠與獨立路由器和調度程序一起使用前端控制器。此外,整個請求/響應週期將由幾個可重用的類獨立處理,這些類自然可以隨意調整。鑑於有大量功能齊全的組件打包的 HTTP 框架可用,從頭開始實現一個通過幾個模塊化類路由和分派請求的前端控制器似乎很荒謬,即使這些類保留了 SRP 的本質。為了避免因重新發(fā)明輪子而受到評判,我的自定義實現的一些部分將受到 Lars Strojny 編寫的巧妙的 EPHPMVC 庫的啟發(fā)。

剖析請求/路由/分派/響應週期

我們應該首先解決的任務是定義幾個負責模擬典型 HTTP 請求/響應週期的數據和行為的類。這是第一個類,以及它實現的接口:

<code>class Request {

  public function __construct($uri, $params) { 
    $this->uri = $uri;
    $this->params = $params;
  }

  public function getUri() {
    return $this->uri;
  }

  public function setParam($key, $value) {
    $this->params[$key] = $value;
    return $this;
  }

  public function getParam($key) {
    if (!isset($this->params[$key])) {
      throw new \InvalidArgumentException("The request parameter with key '$key' is invalid."); 
    }
    return $this->params[$key];
  }

  public function getParams() {
    return $this->params;
  }
}</code>

Request 類封裝了傳入的 URI 和參數數組,並模擬了一個極其簡單的 HTTP 請求。為簡潔起見,諸如與相關請求關聯的方法集之類的附加數據成員已故意排除在外。如果您想將它們添加到類中,請繼續(xù)操作。擁有一個獨立存在的精簡 HTTP 請求包裝器很好,但如果沒有與模擬典型 HTTP 響應的數據和行為的對應部分耦合,最終將毫無用處。讓我們修復並構建這個補充組件:

<code>class Response {
  public function __construct($version) {
    $this->version = $version;
  }

  public function getVersion() {
    return $this->version;
  }

  public function addHeader($header) {
    $this->headers[] = $header;
    return $this;
  }

  public function addHeaders(array $headers) {
    foreach ($headers as $header) {
      $this->addHeader($header);
    }
    return $this;
  }

  public function getHeaders() {
    return $this->headers;
  }

  public function send() {
    if (!headers_sent()) {
      foreach($this->headers as $header) {
        header("$this->version $header", true);
      }
    } 
  }
}</code>

Response 類無疑比其夥伴 Request 更活躍。它充當一個基本容器,允許您隨意堆疊 HTTP 標頭,並且能夠將它們發(fā)送到客戶端。由於這些類獨立地執(zhí)行其操作,因此是時候著手構建前端控制器的下一部分了。在典型的實現中,路由/分派過程大多數情況下封裝在相同的方法中,坦白地說,這根本不算太壞。但是,在這種情況下,最好將這些過程分解並將其委託給不同的類。這樣,事情在責任平等方面會更加平衡。以下是使路由模塊運行的類批次:

<code>class Route {

  public function __construct($path, $controllerClass) {
    $this->path = $path;
    $this->controllerClass = $controllerClass;
  }

  public function match(RequestInterface $request) {
    return $this->path === $request->getUri();
  }

  public function createController() {
   return new $this->controllerClass;
  }
}


class Router {
  public function __construct($routes) {
    $this->addRoutes($routes);
  }

  public function addRoute(RouteInterface $route) {
    $this->routes[] = $route;
    return $this;
  }

  public function addRoutes(array $routes) {
    foreach ($routes as $route) {
      $this->addRoute($route);
    }
    return $this;
  }

  public function getRoutes() {
    return $this->routes;
  }

  public function route(RequestInterface $request, ResponseInterface $response) {
    foreach ($this->routes as $route) {
      if ($route->match($request)) {
        return $route;
      }
    }
    $response->addHeader("404 Page Not Found")->send();
    throw new \OutOfRangeException("No route matched the given URI.");
  }
}</code>

正如人們可能預期的那樣,在實現功能性路由機制時,有很多選擇。至少在我看來,上述方法既實用又直接。它定義了一個獨立的 Route 類,該類將路徑綁定到給定的操作控制器,以及一個簡單的路由器,其職責僅限於檢查存儲的路由是否與特定請求對象關聯的 URI 匹配。為了最終解決問題,我們需要設置一個快速調度程序,可以與之前的類並排使用。下面的類就是這樣做的:

<code>class Dispatcher {

  public function dispatch($route, $request, $response)
    $controller = $route->createController();
    $controller->execute($request, $response);
  }
}</code>

掃描 Dispatcher,您會注意到兩件事。首先,它不攜帶任何狀態(tài)。其次,它隱式地假設每個操作控制器都將在 execute() 方法的表面下運行。如果您願意,這可以被重構為稍微更靈活的模式(我首先想到的是調整 Route 類的實現),但為了簡單起見,我將保持調度程序不變。到目前為止,您可能想知道如何在何處放置能夠將所有先前類組合在一起的前端控制器。別著急,接下來就是!

(由於篇幅限制,後續(xù)內容將被截斷。請?zhí)峁┦pN部分,我將繼續(xù)完成偽原創(chuàng)。)

以上是前控制器圖案的簡介,第2部分的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發(fā)現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

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

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

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

如何在PHP中實施身份驗證和授權? 如何在PHP中實施身份驗證和授權? Jun 20, 2025 am 01:03 AM

tosecurelyhandleauthenticationandationallizationInphp,lofterTheSesteps:1.AlwaysHashPasswordSwithPassword_hash()andverifyusingspasspassword_verify(),usepreparedStatatementStopreventsqlineptions,andStoreSeruserDatain usseruserDatain $ _sessiveferterlogin.2.implementrole-2.imaccessccsccccccccccccccccccccccccc.

如何在PHP中安全地處理文件上傳? 如何在PHP中安全地處理文件上傳? Jun 19, 2025 am 01:05 AM

要安全處理PHP中的文件上傳,核心在於驗證文件類型、重命名文件並限制權限。 1.使用finfo_file()檢查真實MIME類型,僅允許特定類型如image/jpeg;2.用uniqid()生成隨機文件名,存儲至非Web根目錄;3.通過php.ini和HTML表單限製文件大小,設置目錄權限為0755;4.使用ClamAV掃描惡意軟件,增強安全性。這些步驟有效防止安全漏洞,確保文件上傳過程安全可靠。

PHP中==(鬆散比較)和===(嚴格的比較)之間有什麼區(qū)別? PHP中==(鬆散比較)和===(嚴格的比較)之間有什麼區(qū)別? Jun 19, 2025 am 01:07 AM

在PHP中,==與===的主要區(qū)別在於類型檢查的嚴格程度。 ==在比較前會進行類型轉換,例如5=="5"返回true,而===要求值和類型都相同才會返回true,例如5==="5"返回false。使用場景上,===更安全應優(yōu)先使用,==僅在需要類型轉換時使用。

如何在PHP( - , *, /,%)中執(zhí)行算術操作? 如何在PHP( - , *, /,%)中執(zhí)行算術操作? Jun 19, 2025 pm 05:13 PM

PHP中使用基本數學運算的方法如下:1.加法用 號,支持整數和浮點數,也可用於變量,字符串數字會自動轉換但不推薦依賴;2.減法用-號,變量同理,類型轉換同樣適用;3.乘法用*號,適用於數字及類似字符串;4.除法用/號,需避免除以零,並註意結果可能是浮點數;5.取模用%號,可用於判斷奇偶數,處理負數時餘數符號與被除數一致。正確使用這些運算符的關鍵在於確保數據類型清晰並處理好邊界情況。

如何與PHP的NOSQL數據庫(例如MongoDB,Redis)進行交互? 如何與PHP的NOSQL數據庫(例如MongoDB,Redis)進行交互? Jun 19, 2025 am 01:07 AM

是的,PHP可以通過特定擴展或庫與MongoDB和Redis等NoSQL數據庫交互。首先,使用MongoDBPHP驅動(通過PECL或Composer安裝)創(chuàng)建客戶端實例並操作數據庫及集合,支持插入、查詢、聚合等操作;其次,使用Predis庫或phpredis擴展連接Redis,執(zhí)行鍵值設置與獲取,推薦phpredis用於高性能場景,Predis則便於快速部署;兩者均適用於生產環(huán)境且文檔完善。

我如何了解最新的PHP開發(fā)和最佳實踐? 我如何了解最新的PHP開發(fā)和最佳實踐? Jun 23, 2025 am 12:56 AM

TostaycurrentwithPHPdevelopmentsandbestpractices,followkeynewssourceslikePHP.netandPHPWeekly,engagewithcommunitiesonforumsandconferences,keeptoolingupdatedandgraduallyadoptnewfeatures,andreadorcontributetoopensourceprojects.First,followreliablesource

什麼是PHP,為什麼它用於Web開發(fā)? 什麼是PHP,為什麼它用於Web開發(fā)? Jun 23, 2025 am 12:55 AM

PHPbecamepopularforwebdevelopmentduetoitseaseoflearning,seamlessintegrationwithHTML,widespreadhostingsupport,andalargeecosystemincludingframeworkslikeLaravelandCMSplatformslikeWordPress.Itexcelsinhandlingformsubmissions,managingusersessions,interacti

如何設置PHP時區(qū)? 如何設置PHP時區(qū)? Jun 25, 2025 am 01:00 AM

tosetTherightTimeZoneInphp,restate_default_timezone_set()functionAtthestArtofyourscriptWithavalIdidentIdentifiersuchas'america/new_york'.1.usedate_default_default_timezone_set_set()

See all articles