mcpField
L
laravel-query-builders

laravel-query-builders

github.com/leeovery开发1554 次安装2 周前更新
代码仓库

关于 laravel-query-builders

面向 Laravel 开发的技能,建议使用自定义 Eloquent 查询构建器代替本地作用域,涵盖类型安全、可组合的查询逻辑、模型注册、复用 Trait 和常见查询模式。

主要功能

  1. 01用自定义构建器替代本地作用域
  2. 02类型安全的嵌套关联查询
  3. 03可复用的查询 Trait
  4. 04在模型中注册构建器
  5. 05组合筛选与关联加载

适用场景

  1. 01在专用构建器中整理订单筛选
  2. 02为关联查询添加类型安全条件
  3. 03复用日期或状态查询逻辑
  4. 04加载关联模型并分页结果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/leeovery/agentic-skills --skill laravel-query-builders

安装后在 Claude Code 中输入/laravel-query-builders确认已加载。

详细介绍

Laravel 查询构建器

始终使用自定义查询构建器,而不是本地作用域。

相关指南:

  • 模型 - 将模型与自定义构建器集成
  • 控制器 - 在控制器中使用查询对象

为什么优先选择自定义构建器,而不是作用域

❌ 不要使用本地作用域。

✅ 使用自定义查询构建器,因为它们具备以下优势:

  1. 类型提示更好 - IDE 自动补全更完善
  2. 嵌套查询类型安全 - 可在 whereHas()、orWhereHas() 等方法中为闭包添加类型提示
  3. 组织更清晰 - 所有查询逻辑都集中在一个类中
  4. 组合性更强 - 更容易进行链式调用和组合
  5. 更易测试 - 可单独测试查询逻辑

基本构建器结构

<?php

declare(strict_types=1);

namespace App\Builders;

use App\Enums\OrderStatus;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;

class OrderBuilder extends Builder
{
    public function wherePending(): self
    {
        return $this->where('status', OrderStatus::Pending);
    }

    public function whereCompleted(): self
    {
        return $this->where('status', OrderStatus::Completed);
    }

    public function whereCustomer(User|int $customer): self
    {
        $customerId = $customer instanceof User ? $customer->id : $customer;
        return $this->where('customer_id', $customerId);
    }

    public function whereTotalGreaterThan(int $amount): self
    {
        return $this->where('total', '>', $amount);
    }

    public function wherePlacedBetween(Carbon $start, Carbon $end): self
    {
        return $this->whereBetween('placed_at', [$start, $end]);
    }

    public function withRelated(): self
    {
        return $this->with(['customer', 'items.product', 'shipments']);
    }

    public function recent(): self
    {
        return $this->latest('placed_at');
    }
}

类型安全的嵌套查询

为闭包添加类型提示,以便在关系查询中获得完整的 IDE 支持:

public function whereHasItems(array|string $productIds): self
{
    return $this->whereHas('items', function (OrderItemBuilder $query) use ($productIds): void {
        $query->whereIn('product_id', (array) $productIds);
    });
}

用法:

Order::query()
    ->whereHas('items', function (OrderItemBuilder $query): void {
        $query->whereActive()        // Custom method - autocomplete works!
              ->whereProduct($id);   // Full type safety!
    })
    ->whereHas('customer', function (CustomerBuilder $query): void {
        $query->whereVerified()      // Custom method
              ->wherePremium();      // IDE knows all methods!
    })
    ->get();

外部方法的 PHPDoc

为 Spatie 软件包或宏中的方法添加文档说明:

/**
 * @method static OrderBuilder whereState(string $column, string|array $state)
 * @method static OrderBuilder whereNotState(string $column, string|array $state)
 */
class OrderBuilder extends Builder
{
    // ...
}

构建器 Trait

提取可复用的查询逻辑:

<?php

declare(strict_types=1);

namespace App\Builders\Concerns;

use Illuminate\Support\Arr;

trait HasProducts
{
    public function whereHasProducts(array|string $productIds): self
    {
        return $this->whereHas('products', function ($query) use ($productIds): void {
            $query->whereIn('id', Arr::wrap($productIds));
        });
    }

    public function whereHasActiveProducts(): self
    {
        return $this->whereHas('products', function ($query): void {
            $query->where('active', true);
        });
    }
}

在构建器中的用法:

class OrderBuilder extends Builder
{
    use HasProducts;

    // ...
}

在模型中注册构建器

首选:PHP Attribute(Laravel 12+)
use Illuminate\Database\Eloquent\Attributes\UseEloquentBuilder;

#[UseEloquentBuilder(OrderBuilder::class)]
class Order extends Model
{
    // ...
}
备用方案:重写方法(Laravel 12 之前)
public function newEloquentBuilder($query): OrderBuilder
{
    return new OrderBuilder($query);
}

用法示例

基本链式调用
Order::query()
    ->wherePending()
    ->whereTotalGreaterThan(10000)
    ->wherePlacedBetween(now()->subWeek(), now())
    ->withRelated()
    ->recent()
    ->paginate();
惰性迭代
Order::query()
    ->whereCompleted()
    ->lazyById()
    ->each(function (Order $order): void {
        // Process order
    });
复杂查询
$orders = Order::query()
    ->wherePending()
    ->whereCustomer($user)
    ->whereHasItems([$productId1, $productId2])
    ->wherePlacedBetween($startDate, $endDate)
    ->withRelated()
    ->get();

空构建器

始终创建构建器,即使初始内容为空——以便未来扩展:

<?php

declare(strict_types=1);

namespace App\Builders;

use Illuminate\Database\Eloquent\Builder;

class CustomerBuilder extends Builder
{
    // Empty for now, but ready for future methods
}

常见构建器方法

状态筛选
public function whereActive(): self
{
    return $this->where('status', 'active');
}

public function whereInactive(): self
{
    return $this->where('status', 'inactive');
}
日期范围
public function whereCreatedAfter(Carbon $date): self
{
    return $this->where('created_at', '>', $date);
}

public function whereCreatedToday(): self
{
    return $this->whereDate('created_at', today());
}
用户/所有者筛选
public function whereUser(User|int $user): self
{
    $userId = $user instanceof User ? $user->id : $user;
    return $this->where('user_id', $userId);
}
关系加载
public function withFullRelations(): self
{
    return $this->with([
        'user',
        'items.product',
        'customer.address',
    ]);
}

构建器组织

app/Builders/
├── OrderBuilder.php
├── CustomerBuilder.php
├── ProductBuilder.php
└── Concerns/
    ├── HasProducts.php
    ├── HasDates.php
    └── HasStatus.php

评论

支持 Markdown