跟控制器說再見吧,從今天開始使用請求處理器(Request Handlers) 範式

在過去幾年中, PHP 開發環境發生了很大的變化。咱們開始使用更多更好的設計模式,好比 DRYSOLID) 設計模式原則。但爲何咱們仍然在使用控制器?php

若是您之前曾經參與過大型項目的架構編寫,那麼您可能已經注意到早晚會出現控制器過多的這種現象。即便您將控制器邏輯分離到各類類庫或服務類中,大量的依賴項和方法以及代碼的行數仍是會隨着時間的推移不斷增加。laravel

我來介紹一下請求處理器。這個概念很簡單,但不少 PHP 開發人員都不知道。請求處理器能夠理解爲僅包含單個動做(Action)的控制器,可以使請求到響應的流程更加清晰明確。這個概念與 Paul M. Jones 提出的 Action-Domain-Responder 設計模式有類似之處,後者是MVC模式的替代品。git

file

一個好的方法去創建請求處理器就是使用調用類。可調用類是使用PHP中的魔術方法 __invoke ,把他們變成一個 Callable ,這將容許他們做爲函數調用。這裏有一個關於調用類的簡單例子:github

class Greeting
{
    public function __invoke($name)
    {
        echo 'Hello ' . $name;
    }
}

$welcome = new Greeting();
$welcome('John Doe'); //輸出 Hello John Doe

看到這裏你大概會想;「我爲何要這樣作?」。我知道這是一個有點荒謬的例子。可是它與某些代碼一塊兒使用時例如可調用對象和依賴注入,它將變得頗有意義。一個好的使用例子是路由的請求處理在Laravel和Slim框架中。設計模式

Route::get('/{name}', Greeting::class);

是否讓你大吃一驚?沒有?讓咱們把它和你一般寫的比較一下:架構

Route::get('/{name}', 'SomeController@greeting');

尚未?除了代碼好看以外,還有其餘優勢。讓咱們先去看看使用請求處理程序比控制器有那些優勢。框架

單一模式

SOLID 的第一個原則是「單一模式」。在我看來,控制器中存在許多的方法,就打破了這個原則。請求處理程序提供了一個很好的解決方案,能夠將這些操做分紅它們本身的類,使它們更易於維護,重構和測試。編輯器

這是從 UsersController 中提取的2個請求處理程序的示例,它處理用戶配置文件的編輯和保存:函數

class EditUserHandler
{
    public function __construct(
        UserRepository $repository,
        Twig $twig
    ) {
        ...
    }

    public function __invoke(Request $request, Response $response)
    {
        ...
    }
}

class UpdateUserHandler
{
    public function __construct(
        UserRepository $repository,
        UpdateUserValidator $validator,
        ImageManager $resizer,
        Filesystem $storage
    ) {
        ...
    }

    public function __invoke(Request $request, Response $response)
    {
        ...
    }
}

接下來讓咱們看下一個優點;性能

測試性能

你最近有沒有爲你的項目編寫過單元測試?在編寫單元測試的時候你可能編寫了一些與測試無關的模擬依賴項。因爲請求處理器將不一樣的控制器操做拆分爲單獨的類,所以您只需注入或綁定該動做所須要的依賴項便可。

這是 Jeffrey Way 的一些建議 Twitter

提示:讓你的功能測試儘量更加詳細具體,使用測試用例來描述重要的規則和能力。

這基本不會讓你的請求處理器都有一個測試文件。對於那些繁瑣的控制器測試文件來講是一個很是好的改進。

重構

PhpStorm 和其餘的編輯器都有強大的代碼重構功能,可是若是你使用的是 Laravel 或者 Slim 框架默認的路由方法將控制器綁定到路由,那麼你可能會遇到這種問題。

例如重命名:

Route::get('/{name}', Greeting::class);

比這簡單得不少:

Route::get('/{name}', 'SomeController@greeting');

結論

請求處理器是控制器很好的替代品。控制器的動做(Actions)被分爲多個獨立的請求處理器類,分別負責響應單一的動做。這使整個項目的代碼更易於維護、重構和測試。

您是否應當使用請求處理器替換全部控制器?可能不是。對於小型應用程序而言,爲了簡單,將動做組合成控制器或許更加合理。當我開始在 Teamleader 工做後,我纔開始發掘請求處理器,我以爲近期沒什麼換回控制器的必要了。

若是有什麼不清楚或有疑問,請在下面留下評論告訴我,我會更新這篇文章。

轉自 PHP / Laravel 開發者社區 https://laravel-china.org/top...
相關文章
相關標籤/搜索