深刻理解 Laravel 管道

這是一篇譯文,原文 Understanding Laravel Pipelines。譯文首發於 深刻理解 Laravel 管道,轉載請註明出處。

基本上,你能夠使用 laravel 管道(pipelines)基於鏈式操做將對象傳入多個類中執行任何類型的任務,並在全部「任務」執行完成後一次性返回最終結果。php

你能夠從 Laravel pipelines 獲取更多相關知識。

有關管理工做原理的最多見的示例是在框架自己的組件中的使用。我這裏說的就是「中間件」。html

中間件提供一種方便的機制來過濾發送到應用中的 HTTP 請求...

下面是一個基本的中間件示例:laravel

<?php

namespace App\Http\Middleware;

use Closure;

class TestMiddleware
{
    /**
     * 處理請求
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // 在這裏加入你的代碼

        return $next($request);
    }
}

這些「中間件」實際上就是管道經過接受傳入的請求,來處理執行所需的任務。在這裏你能夠來檢測當前接受的請求是一個 HTTP 請求、JSON 請求或任何用戶認證等工做。編程

若是你快速瀏覽過 Illuminate\Foundation\Http\Kernel 類,你會看到中間件是如何在 Pipeline 對象中被執行的。bootstrap

/**
  * 將請求傳入到指定的 中間件/路由。

  * @param  \Illuminate\Http\Request  $request
  * @return \Illuminate\Http\Response
  */
protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);
    Facade::clearResolvedInstance('request');
    $this->bootstrap();
    return (new Pipeline($this->app))
                    ->send($request)
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
    ->then($this->dispatchToRouter());
}

你能夠從這段代碼中看到:pipeline 實例將請求發送到一組中間件中,並將其分發到路由器。api

若是這段代碼對你來講有些手足無措的話請不用擔憂。我將以一些實例來闡明它的相關概念。閉包

在類中運行多個任務(Working on a class that requires to run multiple tasks)

考慮一下這樣的場景。咱們須要建立一個容許用戶建立話題和留言功能的論壇系統。但客戶端在它們建立或編輯時要求你自動刪除標籤。app

下面是你須要作的事情:框架

  1. 替換文本中的 link 標籤。
  2. 使用「*」替換掉敏感詞。
  3. 移除文本中的 script 標籤。

也許最終你會構建相關的類來處理這些「任務」。post

$pipes = [
    RemoveBadWords::class
    ReplaceLinkTags::clas
    RemoveScriptTags::class
];

咱們要作的就是將咱們的「內容」依次傳入每一個任務,而後將上一個任務處理結果傳入到下一個任務。咱們能夠使用管道來處理這個任務。

public function create(Request $request)
{
    $pipes = [
        RemoveBadWords::class,
        ReplaceLinkTags::class,
        RemoveScriptTags::class
    ];

    $post = app(Pipeline::class)
    ->send($request)
    ->through($pipes)
    ->then(function ($content) {
        return Post::create(['content' => $content]);
    });

    // 返回響應
}

每一個「任務」類都須要定義一個「handle」方法來處理功能。也許經過實現接口編程是一個不錯的主意:

<?php

namespace App;

use Closure;

interface Pipe
{
    public function handle($content, Closure $next);
}
  • 命名好難啊 ¯_(ツ)_/¯*
<?php

namespace App;

use Closure;

class RemoveBadWords implements Pipe
{
    public function handle($content, Closure $next)
    {
        // 在這裏處理任務,返回待更新的 **$content** 給到下一個管道任務。
        return  $next($content);
    }
}

用於處理任務的方法接收兩個參數,第一個是一個可傳遞的對象,第二個是閉包,在運行最後一個管道後對象將被重定向到這個閉包。

你也能夠自定義方法名來替代「handle」方法名。而後您須要指定管道要使用的方法名,就像這樣:

app(Pipeline::class)
 ->send($content)
 ->through($pipes)
 ->via('customMethodName') // <---- 就是這個 :)
 ->then(function ($content) {
     return Post::create(['content' => $content]);
 });

最後發生了什麼?(What happens at the end ?)

這裏應該發生的是提交的內容將會被每一個 &dollar;pipes 修改,最終的返回的內容將被保存。

$post = app(Pipeline::class)
    ->send($request->all())
    ->through($pipes)
    ->then(function ($content) {
        return Post::create(['content' => $content]);
    });

結束語(Final words)

記住, 有不少方法能夠處理這種類型的問題。如何選擇取決於你。可是值得高興的是在你的知識庫中在須要的時候已經創建了管道這個新的武器的知識。

我但願這個實例可以讓你對「Laravel Pipelines」有更深如的瞭解,並知道如何使用它們。

你也能夠去查看 laravel api 文檔,若是你但願瞭解更多它是如何工做的 https://laravel.com/api/5.4/Illuminate/Pipeline/Pipeline.html

在哪用?(Where to use it ?)

這須要靠你去發現... 若是你有任何好的將以請聯繫我。😉

相關文章
相關標籤/搜索