本文来自pilishen.com----原文链接; 欢迎来和pilishen一起学习php&Laravel;学习群:109256050
该篇属于《Laravel底层核心技术实战揭秘》这一课程《laravel底层核心概念解析》这一章的扩展阅读。考虑到学员们的基础差异,为了避免视频当中过于详细而连篇累牍,故将一些laravel底层实现相关的PHP知识点以文章形式呈现,供大家预习和随时查阅。
基本上,使用laravel pipelines你可以将一个实例对象(object)在多个类之间传递,就像流水顺着管道依次流淌一般,最终呢,层层传递,你就得到了从头至尾一系列执行操作的“最终”结果。
当然,laravel里pipeline(管道、通道)相关的,最直接的例子就是Middleware了。借助这种通道方式,Middleware可以很方便地层层“过滤”(filter)进入你程序中的request。
下面是一个基本的Middleware例子:
<?php
namespace App\Http\Middleware;
use Closure;
class TestMiddleware
{
public function handle($request, Closure $next)
{
// 这里添加自己的逻辑
return $next($request);
}
}
复制代码
middleware就像是我们的request请求流经的“管道”,这期间可以执行必要的操作,比如判断当前请求是一个http请求呢,还是一个json请求呢,或者也可以检查一下用户的权限,或许这个时候你就会想到我们laratrust(或Entrust)插件一系列经典的Middleware。
在《Laravel底层核心技术实战揭秘》课程里,涉及到service provider的加载注册原理和源码解读的时候,我们一起看过Illuminate\Foundation\Http\Kernel
这个class,期间呢详细分析了sendRequestThroughRouter
这个方法:
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());
}
复制代码
注意return
后面的那段,看字面意思都很好理解:
一个
new Pipeline
发送了(send)request请求,通过了(through)我们的Middleware,然后(then)提交给了路由。
例子:实现一个需要依次处理多个任务的类(class)逻辑
假设呢你在写一个论坛功能,用户呢可以创建话题、评论话题,但是呢,你的客户要求你实现一个能自动替换删除某些内容、符号的功能,数据处理了以后呢才能写入数据库,比如说具体的需求列表是这样的:
- 删除那些没有href的空的链接
- 将一些敏感词汇替换成星号
*
- 删掉用户提交可能危险的script tag
很可能最后呢,你需要实现下面的这个处理过程:
$pipes = [
RemoveBadWords::class
ReplaceLinkTags::class
RemoveScriptTags::class
];
复制代码
我们需要的是,将需要处理的内容依次传递到这三个class中,上一个class的执行结果要传给下一个class来继续处理,那么类似的需求,我们就可以使用pipeline
来实现:
<?php
public function create(Request $request)
{
$pipes = [
RemoveBadWords::class,
ReplaceLinkTags::clas,
RemoveScriptTags::class
];
$post = app(Pipeline::class)
->send($request->content)
->through($pipes)
->then(function ($content) {
return Post::create(['content' => 'content']);
});
// return any type of response
}
复制代码
每一个数据处理的class,都应该有一个handle
方法来执行具体的逻辑,所以这个时候让它们都扩展或实现某个特定的interface比较好:
<?php
namespace App;
use Closure;
interface Pipe
{
public function handle($content, Closure $next);
}
复制代码
然后呢假设我们过滤敏感词的class就可以这样写:
<?php
namespace App;
use Closure;
class RemoveBadWords implements Pipe
{
public function handle($content, Closure $next)
{
//具体的替换逻辑,更新掉$content
return $next($content);
}
}
复制代码
这里handle方法接收两个参数,第一个是你要在管道中传递的对象(passable object),第二个呢是一个Closure,也即是匿名函数,它指代你管道中的下一步,当前这一步的逻辑执行完了,就可以把结果传给下一步。
你也可以不用handle
这个方法名,但这个时候你需要通过via
方法来指定自定义方法的名字:
app(Pipeline::class)
->send($content)
->through($pipes)
->via(‘customMethodName’) // <---- 在这儿指定
->then(function ($content) {
return Post::create(['content' => $content]);
});
复制代码
原文出处://medium.com/@jeffochoa/understanding-laravel-pipelines-a7191f75c351