戏里戏外

Laravel Pipeline

2025-01-22#Laravel

Laravel Pipeline 是一个强大的设计模式实现,它允许通过定义一系列可重用的管道来优雅地处理数据。

通过 Pipeline 可以将复杂的数据处理逻辑拆分成小的、独立的步骤,使代码更具可维护性和可测试性。

要使用 Pipeline,可以创建 Illuminate\Pipeline\Pipeline 类的实例并定义管道和要处理的数据:

use Illuminate\Pipeline\Pipeline;

Pipeline::send($data)
    ->through($pipes)
    ->thenReturn();

示例一 处理评论

当需要处理用户评论时,可以使用Laravel 的 Str 类来处理评论中的敏感词,也可以使用 Pipeline 来处理评论中的敏感词。

use Closure;
use Illuminate\Support\Facades\Pipeline;

$comment = " Hey you :-) ";

Pipeline::send($comment)
  ->through([
    function (string $comment, Closure $next) {
      $comment = trim($comment);

      return $next($comment);
    },

    function (string $comment, Closure $next) {
      $comment = str_replace(':-)', '😊', $comment);

      return $next($comment);
    },
  ])
  ->thenReturn();
use Illuminate\Support\Str;

$comment = " Hey you :-) ";

Str::of($comment)->trim()->replace(':-)', '😊')->toString();

示例二 搜索

当需要根据名称、国家或角色搜索和排序时,有多种实现方式。

if 条件

使用 if 条件判断来完成类似的需求。

$usersQuery = User::query();

if ($request->has('name')) {
    $usersQuery->where('name', 'like', "%{$request->get('name')}%");
}

if ($request->has('role')) {
    $usersQuery->where('role', $request->get('role'));
}

if ($request->has('country')) {
    $usersQuery->where('country', $request->get('country'));
}

$usersQuery->orderByDesc('id');

$usersQuery->paginate();

when 方法

使用 Eloquent 的 when 方法来完成类似的需求。

$usersQuery = User::query();

$usersQuery->when($request->has('name'), fn ($query) => $query->where('name', 'like', "%{$request->get('name')}%"));
$usersQuery->when($request->has('role'), fn ($query) => $query->where('role', $request->get('role')));
$usersQuery->when($request->has('country'), fn ($query) => $query->where('country', $request->get('country')));

$usersQuery->orderByDesc('id');

$usersQuery->paginate();

Pipeline

使用 Pipeline 来完成类似的需求,具体代码可以查看这个仓库:laravel-pipeline-demo

use App\Filters\ByName;
use App\Filters\ByRole;
use App\Filters\ByCountry;
use App\Filters\SortUsers;

$pipes = [
    new ByName($request->get('name')),
    new ByRole($request->get('role')),
    new ByCountry($request->get('country')),
    SortUsers::class,
];

Pipeline::send(User::query())
    ->through($pipes)
    ->thenReturn()
    ->paginate();
<?php

namespace App\Filters;

use Closure;
use Illuminate\Database\Eloquent\Builder;

final class ByCountry
{
    public function __construct(protected ?string $country)
    {
        //
    }

    public function handle(Builder $query, Closure $next)
    {
        return $next($query)->when(
            $this->country,
            fn ($query) => $query->where('country', $this->country)
        );
    }
}
<?php

namespace App\Filters;

use Closure;
use Illuminate\Database\Eloquent\Builder;

final class ByName
{
    public function __construct(protected ?string $name)
    {
        //
    }

    public function handle(Builder $query, Closure $next)
    {
        return $next($query)->when(
            $this->name,
            fn (Builder $query) => $query->where('name', 'like', "%{$this->name}%")
        );
    }
}
<?php

namespace App\Filters;

use Closure;
use Illuminate\Database\Eloquent\Builder;

final class ByRole
{
    public function __construct(protected ?string $role)
    {
        //
    }

    public function handle(Builder $query, Closure $next)
    {
        return $next($query)
            ->when(
                $this->role,
                fn ($query) => $query->where('role', $this->role)
            );
    }
}
<?php

namespace App\Filters;

use Closure;
use Illuminate\Database\Eloquent\Builder;

final class SortUsers
{
    public function handle(Builder $query, Closure $next)
    {
        return $next($query)->orderByDesc('id');
    }
}

每个管道都根据用户提供的条件应用特定的筛选或排序操作,最后返回经过过滤和排序的用户。

更多关于 Pipeline 的使用方法可以参考 Laravel Gems - Pipelines在实际场景中使用 Laravel Pipeline:实际示例Laravel Pipelines: Build an Api