Laravel 5.3 请求处理管道详解

对于一个Web应用来说,在一个请求真正处理前,我们可能会对请求做各种各样的判断,然后才允许后续处理。

我们通常的做法:

Script 01.php

 

Script 02.php

 

优点:直观,容易理解

缺点:

  1. 所有处理步骤放在一起,修改添加新步骤可能影响已有步骤;
  2. 单个处理步骤不具备可复用性。
  3. 同一个处理步骤的代码存在于多处,一个需求变更可能要修改多处代码。
  4. 整个处理流程不易扩展

Laravel 的请求处理管道:

 

 

Request,Middleware,Pipeline,Response

一个请求的处理,需要经过很多步骤(中间件),每个处理步骤(中间件)单独添加和修改,处理步骤(中间件)之间可以动态组合,从而使得每个处理步骤(中间件)可重用,也使得整个处理过程具备可扩展性。

Laravel 这种灵活的、可扩展的处理机制是如何实现的? ----- 管道模式(Pipeline

何为管道?

先来看一下自来处理流程:

 

 

原水,处理池,水管,饮用水

原水通过水管流经每个处理池,每个处理池中对水进行特定的处理,最后从水管中流出饮用水。

整个处理系统中,处理池可以随处理工艺的变更随时进行替换/新增/移除。

管道模式:

将整个处理流程划分成多个子任务,每个子任务对应一个任务模块,任务模块之间互相独立。当需要处理数据时,将本次所需任务模块按处理流程组装起来,前一个模块的输出作为后一个模块的输入,最后一个模块的输出即为最终处理结果。

 

 

输入数据,子处理模块,管道,输出数据
优点:
1. 各子模块相对独立
2. 每个子模块可复用
3. 处理流程可扩展(可以根据需求的不同,选择不同的子模块进行组合,满足要求)

用PHP实现管道模式:

 1 <?php
 2 
 3 /**
 4  * 管道 Demo
 5  */
 6 
 7 interface Middleware
 8 {
 9     public function handle();
10 }
11 
12 class MyRequest implements Middleware
13 {
14     public function handle()
15     {
16         echo "【处理请求,返回响应】<br />";
17     }
18 }
19 
20 abstract class MiddlewareAbstract implements Middleware
21 {
22     protected $next;
23     
24     public function __construct(Middleware $middleware)
25     {
26         $this->next = $middleware;
27     }
28 }
29 
30 class VerifyCsrfToken extends MiddlewareAbstract
31 {    
32     public function handle()
33     {
34         echo "验证 CSRF Token<br />";
35         $this->next->handle();
36         echo "添加 CSRF Token<br />";
37     }
38 }
39 
40 class StartSession extends MiddlewareAbstract
41 {
42     public function handle()
43     {
44         echo "开启 Session,获取会话数据<br />";
45         $this->next->handle();
46         echo "保存会话数据,关闭 Session<br />";
47     }
48 }
49 
50 class EncryptCookies extends MiddlewareAbstract
51 {
52     public function handle()
53     {
54         echo "对输入 Cookie 进行解密<br />";
55         $this->next->handle();
56         echo "对输出 Cookie 进行加密";
57     }
58 }
59 
60 class CheckMaintenanceMode extends MiddlewareAbstract
61 {
62     public function handle()
63     {
64         echo "检测系统是否处于维护状态<br />";
65         $this->next->handle();
66     }
67 }
68 
69 class MyMiddleware extends MiddlewareAbstract
70 {
71     public function handle(){
72         echo "我新增的中间件<br />";
73         $this->next->handle();
74     }
75 }
76 
77 $pipeline = new CheckMaintenanceMode(//检测系统是否处于维护状态
78     new EncryptCookies(//Cookie 加解密
79         new StartSession(//Session 相关处理
80              new MyMiddleware(
81                 new VerifyCsrfToken(//Csrf Token 处理
82                     new MyRequest() //处理请求,返回响应
83                 )
84              )
85         )
86     )
87 );
88 
89 $pipeline->handle();

Laravel 中管道的实现:

<?php
/** * Laravel 管道 */ interface Middleware { public function handle(Closure $next); } class VerifyCsrfToken implements Middleware { public function handle(Closure $next) { echo "验证 CSRF Token<br />"; $next(); echo "添加 CSRF Token<br />"; } } class StartSession implements Middleware { public function handle(Closure $next) { echo "开启 Session,获取会话数据<br />"; $next(); echo "保存会话数据,关闭 Session<br />"; } } class EncryptCookies implements Middleware { public function handle(Closure $next) { echo "对输入 Cookie 进行解密<br />"; $next(); echo "对输出 Cookie 进行加密"; } } class CheckMaintenanceMode implements Middleware { public function handle(Closure $next) { echo "检测系统是否处于维护状态<br />"; $next(); } } /** * 处理流程: * 1. 检测系统是否处于维护状态 * 2. 对输入 Cookie 进行解密 * 3. 开启 Session,获取会话数据 * 4. 验证 CSRF Token * 5. 处理请求,返回响应 * 6. 添加 CSRF Token * 7. 保存会话数据,关闭 Session * 8. 对输出 Cookie 进行加密 */ function process() { $pipes = [ CheckMaintenanceMode::class, EncryptCookies::class, StartSession::class, VerifyCsrfToken::class, ]; $firstSlice = function () { echo "【处理请求,返回响应】<br />"; }; $pipes = array_reverse($pipes); $callStack = array_reduce($pipes, getSlice(), $firstSlice); $callStack(); } function getSlice() { return function ($stack, $pipe) { return function () use ($stack, $pipe) { return (new $pipe)->handle($stack); }; }; } process();

 

posted @ 2016-11-17 14:12  猿界小学生  阅读(403)  评论(0编辑  收藏  举报