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

在Laravel中如何使用Eloquent排除无关联销售记录的库存商品?

Eloquent实现库存商品按最新销售记录排序方案

需求为筛选有销售记录的商品、按最新销售时间排序,以下两种实现方式均可:

一、优化你现有JOIN写法

你原有代码逻辑没问题,但存在两个兼容风险:

  1. 若MySQL开启了ONLY_FULL_GROUP_BY严格模式,仅按inventory_sell_records.product_id分组会触发字段不兼容报错
  2. 直接拼接$order_by变量存在SQL注入风险

优化后代码:

// 提前校验排序方向,仅允许asc/desc
$orderDirection = in_array(strtolower($order_by), ['asc', 'desc']) ? $order_by : 'desc';

$inventory = Inventory::where('inventory.client_id', $user->client_id)
    ->join('inventory_sell_records', 'inventory_sell_records.product_id', '=', 'inventory.id')
    // 按库存表主键分组,兼容SQL严格模式校验
    ->groupBy('inventory.id')
    // 用参数绑定传入排序方向,避免注入风险
    ->orderByRaw("MAX(inventory_sell_records.created_at) ?", [$orderDirection])
    ->paginate(100);

二、更符合Eloquent规范的关联写法

无需手动编写JOIN逻辑,代码可读性和可维护性更高,首先先在Inventory模型中定义一对多关联:

// app/Models/Inventory.php
public function sellRecords()
{
    return $this->hasMany(SellRecord::class, 'product_id', 'id');
}

后续查询直接调用关联方法即可:

$orderDirection = in_array(strtolower($order_by), ['asc', 'desc']) ? $order_by : 'desc';

$inventory = Inventory::where('client_id', $user->client_id)
    // 自动排除无销售记录的商品
    ->whereHas('sellRecords')
    // 关联查询获取该商品最新的销售记录时间,生成字段latest_sold_at
    ->withMax('sellRecords as latest_sold_at', 'created_at')
    // 按最新销售时间排序
    ->orderBy('latest_sold_at', $orderDirection)
    ->paginate(100);

该写法优势:

  • 无需手动处理关联逻辑,Eloquent自动生成查询语句
  • 天然兼容SQL严格模式,不会出现分组报错
  • 查询结果附带latest_sold_at字段,可直接用于前端展示最新销售时间
  • 配合排序方向白名单校验,完全避免SQL注入风险

内容的提问来源于stack exchange,提问作者bohdan baida

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 15:06:03