
在 Laravel Eloquent 中,distinct() 方法需配合 select() 明确指定去重字段,且不能直接与 get() 混用实现单字段去重查询;若需获取去重后的模型集合,必须显式 select('column') 并确保字段兼容模型结构。
在 laravel eloquent 中,`distinct()` 方法需配合 `select()` 明确指定去重字段,且不能直接与 `get()` 混用实现单字段去重查询;若需获取去重后的模型集合,必须显式 `select('column')` 并确保字段兼容模型结构。
Laravel 的 distinct() 方法作用于 SQL 的 SELECT DISTINCT 子句,但它不会自动限制返回字段——这意味着:
- 若未调用 select(),distinct() 会对整行记录(所有选中的列)去重,而 Eloquent 默认 select(*),导致看似“无效”;
- count('column') 是特例:它会生成 COUNT(DISTINCT column),因此 distinct()->count('product_id') 能正确统计唯一产品数;
- 但 get() 不同:distinct()->get() 仍执行 SELECT DISTINCT *,返回的是完整模型实例(含全部字段),只要任意一列不同,整行即不被去重,因此无法达到按单字段(如 product_id)筛选的目的。
✅ 正确做法:若需获取去重后的 product_id 值列表(非模型对象),应使用 pluck():
$customers_id = Order::where('user_id', $id)->pluck('id');
$productIds = OrderItem::whereIn('order_id', $customers_id)
->distinct()
->pluck('product_id'); // 返回 collection of unique product_id values
✅ 若需获取去重后对应的产品模型(如 Product),推荐关联查询而非硬编码去重:
$productIds = OrderItem::whereIn('order_id', $customers_id)
->pluck('product_id')
->unique(); // Collection-level deduplication
$products = Product::whereIn('id', $productIds)->get();
⚠️ 注意事项:
- ❌ 错误写法:->distinct('product_id')->get() —— distinct() 不接受参数(Laravel 9+ 已废弃带参形式),该语法会报错或被忽略;
- ❌ ->distinct()->get() 无法等价于“按某字段去重取模型”,因 Eloquent 模型需完整字段映射,强行 select('product_id') 后 get() 将返回不完整模型(缺少主键、时间戳等),可能引发异常;
- ✅ 推荐原则:去重逻辑优先在数据库层完成(distinct() + pluck()),业务逻辑优先用集合操作(unique())或关联查询,避免语义混淆。
总结:distinct() 是 SQL 层去重指令,不是模型过滤器;与其纠结 get() 配合 distinct(),不如明确意图——要值?用 pluck();要模型?走关联或分步查。清晰的职责分离,才是 Laravel 可维护性的基石。











