Laravel 用 Pipeline 与 Invokable 类把业务流程拆成可组合步骤

test12026-10-2720 次阅读

场景:一个越来越胖的控制器

下单接口里,校验库存、计算优惠、锁定额度、写订单、发通知,全挤在一个方法里,改一处怕动全局。Laravel 的 Pipeline 让每一步成为独立的 invokable 类,按顺序流过,职责清晰、可单独测试。

定义每个步骤

// app/Pipes/CheckStock.php
namespace App\Pipes;

use Closure;

class CheckStock
{
    public function handle($payload, Closure $next)
    {
        if ($payload->items->contains(fn ($i) => $i->stock <= 0)) {
            abort(422, '库存不足');
        }
        return $next($payload);
    }
}

用 Pipeline 串起来

// app/Services/OrderService.php
namespace App\Services;

use App\Pipes\CheckStock;
use App\Pipes\ApplyCoupon;
use App\Pipes\LockQuota;
use App\Pipes\CreateOrder;
use App\Pipes\NotifyUser;
use Illuminate\Pipeline\Pipeline;

class OrderService
{
    public function place($orderDto)
    {
        return app(Pipeline::class)
            ->send($orderDto)
            ->through([
                CheckStock::class,
                ApplyCoupon::class,
                LockQuota::class,
                CreateOrder::class,
                NotifyUser::class,
            ])
            ->then(fn ($payload) => $payload->order);
    }
}

在控制器里只剩一行

public function store(OrderRequest $request, OrderService $service)
{
    $order = $service->place($request->toDto());
    return OrderResource::make($order);
}

工程注意点

  • 每个 Pipe 只做一件事,靠 $next($payload) 往下传,前置校验不通过就 abort。
  • Pipeline 与中间件很像,但它作用于业务对象而非 HTTP 请求,适合把领域流程对象化。
  • 步骤顺序就是业务流程,调整顺序或插新步骤时不影响其它步骤。
  • 单测可以直接 new 出 Pipe 调用 handle,比整条链路测更轻。
T

test1

文章作者

场景:一个越来越胖的控制器 下单接口里,校验库存、计算优惠、锁定额度、写订单、发通知,全挤在一个方法里,改一处怕动全局...

分类
技术
发布时间
2026-10-27
字数
约 1448 字
阅读
20 次