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

Laravel Eloquent如何获取未入库或库存为0的Product集合?

解决Laravel中获取指定仓库缺失或库存为0的产品集合问题

首先我们需要调整模型关联让查询更顺畅,然后实现missingProduct方法:

步骤1:完善Product模型的关联

给Product模型添加与中间表WarehouseProduct的关联,方便后续查询:

class Product extends Model {
    protected $fillable = [
        'name', 'item_number', // ...
    ];

    // 关联仓库产品库存记录
    public function warehouseProducts()
    {
        return $this->hasMany(WarehouseProduct::class);
    }
}

步骤2:实现Warehouse模型的missingProduct方法

这里提供两种高效的实现方式,你可以根据场景和习惯选择:

方式一:Eloquent风格实现(推荐,代码更直观)

use Illuminate\Support\Facades\DB;

class Warehouse extends Model {
    protected $fillable = [
        'name', 'address', // ...
    ];

    public function products() {
        return $this->hasMany(WarehouseProduct::class);
    }

    public function missingProduct() {
        return Product::whereDoesntExist(function ($query) {
            // 筛选当前仓库无记录的产品
            $query->select(DB::raw(1))
                  ->from('warehouse_products')
                  ->whereColumn('warehouse_products.product_id', 'products.id')
                  ->where('warehouse_products.warehouse_id', $this->id);
        })
        ->orWhereHas('warehouseProducts', function ($query) {
            // 筛选当前仓库有记录但库存为0的产品
            $query->where('warehouse_id', $this->id)
                  ->where('amount', 0);
        })
        ->get();
    }
}

方式二:左连接实现(大数据量场景性能更优)

class Warehouse extends Model {
    // ... 其他代码

    public function missingProduct() {
        return Product::leftJoin('warehouse_products', function ($join) {
            $join->on('products.id', '=', 'warehouse_products.product_id')
                 ->where('warehouse_products.warehouse_id', $this->id);
        })
        ->where(function ($query) {
            // 匹配两种情况:无仓库记录 或者 库存为0
            $query->whereNull('warehouse_products.id')
                  ->orWhere('warehouse_products.amount', 0);
        })
        ->select('products.*') // 仅返回产品表字段
        ->distinct() // 避免重复结果
        ->get();
    }
}

额外优化:添加多对多关联(可选)

如果希望更直接地在Warehouse和Product之间建立多对多关联,可以修改Warehouse模型的products方法:

public function products() {
    return $this->belongsToMany(Product::class, 'warehouse_products')
                ->withPivot('amount'); // 携带库存字段
}

此时也可以用更直观的方式实现missingProduct(虽然会多一次查询,但代码可读性更高):

public function missingProduct() {
    // 获取当前仓库已有记录的产品ID
    $existingIds = $this->products()->pluck('products.id');
    // 获取当前仓库库存为0的产品ID
    $zeroStockIds = $this->products()->wherePivot('amount', 0)->pluck('products.id');

    return Product::whereNotIn('id', $existingIds)
                  ->orWhereIn('id', $zeroStockIds)
                  ->get();
}

核心逻辑说明

所有实现方式的核心都是筛选两类产品:

  • 完全没有在当前仓库的warehouse_products表中留下记录的产品
  • 在当前仓库有记录,但amount字段等于0的产品

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 18:37:59