pipeline调用应通过app(pipeline::class)启动,send传入任意类型数据,through传闭包或类名数组,then必须传闭包,中间件handle方法须严格声明handle($passable, closure $next)并return $next($passable)。

别用 foreach 套 if 再套 try-catch 处理一连串校验或转换逻辑——Laravel 的 Pipeline 就是为此设计的,它让顺序执行变得清晰、可测、可插拔。
怎么写一个能跑通的 Pipeline 调用
直接调用 app(Pipeline::class) 是最稳妥的起点,不是静态方法链也不是全局函数。很多人一上来就写 pipe() 或 Pipeline::send(),结果报错 Call to undefined function pipe() 或 Argument 1 passed to Pipeline::send() must be an instance of Illuminate\Contracts\Pipeline\Hub,就是因为没走容器解析。
-
send($data)的 $data 可以是任何类型:数组、Eloquent 模型、DTO 实例,甚至Request -
through()接收的是数组,元素可以是闭包、类名字符串(如CheckInventory::class),或带方法名的数组(如[AuthCheck::class, 'handle']) -
then()必须传闭包,否则返回值是最后一个中间件的返回结果,容易和预期不符 - 每个中间件里必须写
return $next($passable),漏掉这句流程就静默中断,后续步骤完全不执行
中间件类怎么写才不会被容器拒之门外
类名传进 through() 后,Laravel 会从容器里解析实例并调用 handle() 方法。但这个类不是随便写的 Service 类,它得满足隐式契约:
PHP中文网提供Laravel 13.2.0版本下载,Laravel框架 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。
- 方法签名必须是
handle($passable, Closure $next),Closure类型提示不能省,否则 PHP 8+ 会报Too few arguments - 构造函数里可以依赖注入(比如
InventoryService),只要类在容器中可解析(已绑定或符合自动解析规则) - 不要在
handle()里写return $next($passable)->save()这种链式调用——$next()返回的是then()的结果,不是中间态对象 - 如果想提前终止(比如库存不足),直接
throw new Exception('Out of stock'),不用 return false 或 null
什么时候该用 Pipeline,什么时候该绕开
Pipeline 是同步、线性、单输入单输出的流水线,不是万能胶。用错场景反而增加复杂度。
- 适合:API 参数标准化(trim → cast → validate)、订单创建前风控(检查库存 → 用户额度 → 地址有效性)、导出数据前字段脱敏
- 不适合:需要异步执行的步骤(比如发邮件 + 写日志 + 推送通知,应拆成事件或队列)
- 不适合:步骤之间无明确数据依赖(比如“先发短信、再更新状态、最后记录日志”,顺序不关键,用普通方法调用更直白)
- 性能上没额外开销,但每个中间件都是同步阻塞执行,别在里面塞耗时操作(如 HTTP 请求、大文件读写)
真正容易被忽略的点是:Pipeline 的“可插拔”不等于“随意增删”。每个中间件都假设上游已处理好输入格式,下游依赖当前状态——所以改一个中间件,得确认前后接口契约是否还成立,尤其是 $passable 的结构变化。










