laravel管道执行顺序由through()传入的数组顺序严格决定,每个pipe的handle方法通过调用$next($passable)将处理后的$passable传递给下一个pipe,不调用则中断流程。

在 Laravel 中,自定义管道(Pipe)的执行顺序由你传递给 Pipeline 的数组决定,而每一步的结果则取决于前一步的返回值——Laravel 管道采用“线性传递”机制:上一个 Pipe 的返回值会作为参数传给下一个 Pipe 的 handle 方法。
管道执行顺序完全由调用时传入的数组顺序控制
当你使用 app(Pipeline::class) 或 new Pipeline($container) 时,通过 through() 方法传入的 Pipe 类数组,就是实际执行顺序。例如:
$result = app(Pipeline::class)
->send($request)
->through([
EnsureTokenIsValid::class,
EnsureUserIsSubscribed::class,
LogRequestActivity::class
])
->then(fn ($passable) => $passable);
这里三个 Pipe 会严格按数组索引顺序依次执行:先 EnsureTokenIsValid,再 EnsureUserIsSubscribed,最后 LogRequestActivity。
每个 Pipe 的 handle 方法必须调用 $next() 才能继续流程
每个自定义 Pipe 的 handle 方法接收两个参数:$passable(当前传递的数据)和 $next(闭包,代表后续管道)。是否调用 $next($passable) 决定流程是否继续;返回值将作为下一个 Pipe 的输入。常见写法:
- 正常流转:return $next($passable);
- 中断流程(如鉴权失败):直接 return new Response(...); 或 throw 异常,后续 Pipe 不执行
- 修改数据:可对 $passable 做处理后再传给 $next,例如 $passable->merge(['logged' => true])
调试执行过程与结果的实用方法
要直观看到 Pipe 的执行顺序和每步输出,可在各 Pipe 的 handle 中临时加入日志或 dump:
- 用
Log::debug('Pipe X started', ['input' => $passable]);记录输入 - 在
return $next($passable);前加Log::debug('Pipe X passed', ['output' => $passable]); - 开发时可用
dd(get_class($this), $passable);快速确认当前 Pipe 和中间值(注意:dd 会终止流程) - 配合 Laravel Telescope(启用 Pipeline 面板)可自动捕获并可视化整个管道链路
注意 handle 方法签名与容器解析机制
Laravel 默认通过服务容器解析 Pipe 实例,因此 handle 方法的第一个参数是传递的数据($passable),第二个是 $next 闭包。不要在方法中添加额外依赖参数——如有依赖,应通过构造函数注入,而非 handle 参数:
// ✅ 正确:依赖走构造函数
class EnsureTokenIsValid
{
public function __construct(private TokenValidator $validator) {}
public function handle($request, Closure $next)
{
if (! $this->validator->isValid($request->token)) {
throw new InvalidTokenException();
}
return $next($request);
}
}











