mcpField
L
laravel-query-builders

laravel-query-builders

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

关于 laravel-query-builders

面向 Laravel 开发的 Skill,建议使用自定义 Eloquent 查询构建器替代本地作用域,并介绍类型安全的关系查询、方法链和可复用逻辑组织。

主要功能

  1. 01自定义 Eloquent 构建器模式
  2. 02类型安全的嵌套关系查询
  3. 03可链式调用的查询方法
  4. 04可复用的构建器 Trait
  5. 05在模型中注册构建器

适用场景

  1. 01组织订单和客户筛选条件
  2. 02编写类型安全的关系查询
  3. 03在多个构建器间复用查询逻辑

安装

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

$npx skills add https://github.com/leeovery/claude-laravel --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 11+)
use Illuminate\Database\Eloquent\Attributes\UseEloquentBuilder;

#[UseEloquentBuilder(OrderBuilder::class)]
class Order extends Model
{
    // ...
}
替代方案:静态属性
class Order extends Model
{
    protected static string $eloquentBuilder = OrderBuilder::class;

    // ...
}
已弃用:重写方法
// ❌ Don't use this approach anymore
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

总结

自定义查询构建器:

  • 比作用域提供更好的 IDE 支持
  • 支持类型安全的嵌套查询
  • 让查询逻辑井然有序
  • 更易于测试
  • 支持方法链式调用

绝不使用本地作用域——始终使用自定义构建器。

评论

支持 Markdown