You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel/Eloquent中查询包含嵌套去重关联记录的商品数据

方案实现

你不需要让colors表持有stock_id字段,Laravel的hasManyThrough完全适配当前表结构,按如下步骤实现即可:


1. 定义各模型关联

首先在app/Models目录下的三个模型中补充关联定义:

Product 模型
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;

class Product extends Model
{
    // 关联库存表
    public function stocks(): HasMany
    {
        return $this->hasMany(Stock::class);
    }

    // 通过库存表关联颜色表,加distinct去重
    public function colors(): HasManyThrough
    {
        return $this->hasManyThrough(
            Color::class,
            Stock::class,
            'product_id', // Stocks表中关联Products的外键
            'id', // Colors表的主键
            'id', // Products表的主键
            'color_id' // Stocks表中关联Colors的外键
        )->distinct();
    }
}
Stock 模型
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Stock extends Model
{
    // 关联颜色表
    public function color(): BelongsTo
    {
        return $this->belongsTo(Color::class);
    }
}

Color 模型无需额外修改,保持默认即可。


2. 查询数据并格式化输出

直接用预加载查询避免N+1问题,用集合方法处理出你需要的结构:

$products = Product::with(['stocks', 'colors'])
    ->get()
    ->map(function (Product $product) {
        return [
            'id' => (string) $product->id,
            'name' => $product->name,
            // 从库存中提取所有尺码,去重后转为数组
            'available_sizes' => $product->stocks->pluck('size')->unique()->values()->toArray(),
            // 直接取预加载的颜色列表
            'available_colors' => $product->colors->toArray()
        ];
    });

执行后$products的结构完全匹配你给出的期望格式。


可选:用API Resource规范返回

如果是接口返回场景,推荐用Laravel自带的API Resource统一格式化,代码更整洁可复用:

首先创建颜色资源:

php artisan make:resource ColorResource

编辑app/Http/Resources/ColorResource.php:

public function toArray($request)
{
    return [
        'id' => (string) $this->id,
        'name' => $this->name,
        'hex' => $this->hex,
    ];
}

再创建商品资源:

php artisan make:resource ProductResource

编辑app/Http/Resources/ProductResource.php:

use App\Http\Resources\ColorResource;

public function toArray($request)
{
    return [
        'id' => (string) $this->id,
        'name' => $this->name,
        'available_sizes' => $this->stocks->pluck('size')->unique()->values(),
        'available_colors' => ColorResource::collection($this->colors),
    ];
}

接口中直接返回即可:

return ProductResource::collection(Product::with(['stocks', 'colors'])->get());

内容的提问来源于stack exchange,提问作者Touhid Rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 21:30:05