關於 Laravel 5.1 的 Middleware

接觸 Laravel 5.1 的時候看到 middleware 這個資料夾的時候真的有驚訝到,是說,正常人第一眼看到 middleware 的時候會有以下症狀:

* middleware 是什麼?
* 我該怎麼用 middleware?
* 不會寫會怎麼樣嗎? (<- 一定不會怎樣,看你對自己的要求到哪而已 XD)
* 乾眼症

本魯心中也是這兩個問號,不過還好,在剛進敝公司的時候,跟隨同事用 Koa (一個 node.js 的 web framework) 開發 Web Application 的時候,就已經接觸過 Middleware 這個玩意兒了,他說起來確實有點難解釋,抽象,但漸漸抓到它的用處之後,會覺得他真的很好用,使用它最著名的範例,像是 csrf, 權限管理, auth...,下面我會貼上一個 link,大家可以稍微去參考一下那個作者怎麼使用 middleware 做權限管理 (年紀越大越懶得把整份 code 都貼出來講...)。

我先拉回來繼續講 middleware 本身。middleware 有的書會翻中介層,有的會翻中介軟體。它本身的行為可以說是 filter (過濾器),他本身的功能,用意是來隔離網站基礎設施與業務邏輯,至於他的工作範圍,可以說是收到 http request 之後一直到業務邏輯這一段都算,你可以想像你在切一顆洋蔥,那一刀要切下去的時候,就是開始發送 http request,切到中心點時,就是 app 本身的核心功能 (MVC),中間這一段過程,都是 middleware 可以處理事情的地方。

所以那個過程,可以攔截很多資訊,像是在程式還沒跑到 view 時,就先判斷誰有資格看到那個 view,所以這樣的權限功能,就可以寫在 middleware,而不是已經進到 controller 甚至是 view 了,才開始做這些判斷,你一個 app 可能 50 個 controller,難道你要一隻一隻程式各別去加那個判斷嗎? 所以,試著把這些功能抽出來,寫到越前面(底)的地方,提早執行, 不符合條件繼續往下一步就早點 response 回去給 user。

假如今天我寫了一個 middleware,在每個 route 去設定 middleware 以及要 filter 的規格,這樣就算是有用到 middleware 的功能了,不過這樣的設計,或許還可以再更好一點,換言之,我覺得其實 middleware 就是在寫業務邏輯跟流程控制,只是讓他早點發生 XD。(有些文章認為,為每個 route 去設定 middleware 不是很好的設計。)


範例
這裏有篇 Laravel 5 Simple ACL manager 請參考 (這只是個有用到 middleware 的 sample,可以大概看一下,你不要照 copy,除非你要的功能跟邏輯跟他一樣。)。如果你不喜歡這個範例,下面參考也有其他 link。


範例邏輯說明
* 要寫 middleware,首先你要有隻 middleware (你也可以用 php artisan make:middleware 來產生空的檔案,預設 middleware 會放在 app/Http/Middleware ),以上面那個範例來說,作者建立了一隻 CheckRole 的 middleware。
* 在 kernel.php 去註冊你的 middleware (不然誰知道你有 middleware 呢?),註冊的 key 就是使用 middleware 的名稱,如:  'roles' => 'App\Http\Middleware\CheckRole', 使用 middleware 時就是用 roles 那個名字。

放在 App\Http\Kernel.php 的 middleware,算是 global 或是 application 層級的 middleware。 -  翻自 『To add a global or application level middleware, we use the $middleware property of the App\Http\Kernel class.』- Laravel 5 Middleware Stack Decoded 
Route level middlewares can be registered using the $middleware property of the App\Providers\RouteServiceProvider class. - 參考自 Laravel 5 Middleware Stack Decoded 
* 在 middleware 把規則寫出來,做流程控制,哪時候可以通過這個 middleware (return $next($request)),哪時候不行通過,吐個 401 或是 402 跟使用者說掰掰之類的...。
* 在路由控制 (route) 做 middleware,哪幾個 route 需要經過你的 middleware 都要列出來,或者,你也可以把 route 做群組 (group) 之後,再設定 middleware。


小結論
* 合理的使用 middleware。(<- 純嘴砲,我也不知道怎樣算合理?!)
* middleware 也要注意程式有 Exception 的情況。
* 本篇只是小心得,希望大神路過指教 :) 有錯就鞭
* 其實我私心的覺得 L5 把 middleware 變得更好理解一點了,可是 code 比較多,在學 koa 的時候 code 少少的,只要 app.use() 一下就好,可是當時在學的時候,比較難理解...。

參考
https://docs.djangoproject.com/en/1.6/topics/http/middleware/
http://koa.rednode.cn/ 請參考 middleware 那邊有張圖。
http://www.richardbagshaw.co.uk/laravel-5-middleware/
http://www.codeheaps.com/php-programming/laravel-5-middleware-stack-decoded/
http://blog.elliothesp.co.uk/coding/passing-parameters-middleware-laravel-5/

留言

這個網誌中的熱門文章

[Android] 筆記 手機上測試自己的 APP

解決fatal: Not a git repository (or any of the parent directories): .git錯誤

[Android 筆記] 設定 ImageView 的圖檔來源