深刻理解 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 ?)

这须要靠你去发现... 若是你有任何好的将以请联系我。😉

相关文章
相关标签/搜索