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

Laravel如何实现双列条件匹配的belongsTo关联获取产品所有单位

需求背景

现有Units、Products两张数据表,需要获取每个产品对应的全部单位(包含基础单位、子单位)。

表结构说明

Units表

idnamemultiplierbase_unit_id
1Piece1null
2Dozen - 12121

Products表

idnamecostpriceunit_id
1product110141
2product210141

注:原示例中product2的id重复写为1属于笔误,实际应为自增主键

问题描述

在Product模型中定义units关联时,追加orWhere条件匹配base_unit_id等于当前产品unit_id的写法无法正常生效,原有错误写法如下:

public function units()
{
    return $this->belongsTo(Unit::class, 'unit_id', 'id'); // 还需要匹配base_unit_id = 产品unit_id的单位
    // 尝试过的错误写法,无法运行
    // $this->belongsTo(Unit::class, 'unit_id', 'id')->orWhere('base_unit_id', $this->unit_id)
}

期望通过如下预加载写法查询数据,每个产品下的units字段返回包含基础单位、所有子单位的集合:

$products = Product::with('units')->get();

实现方案

之前写法不生效有两个核心问题:

  • 关联类型选错了:一个产品对应多个单位(基础单位+所有子单位),是一对多关系,不能用belongsTo(反向属于关联,只能返回单个模型)
  • 直接在关联里调用$this->unit_id不兼容预加载逻辑:预加载是批量执行查询,此时还未完成模型实例化,拿不到单个产品的unit_id值,必须用字段匹配语法实现跨表条件判断。

正确的模型关联定义写法如下,直接放在Product模型中即可:

public function units()
{
    return $this->hasMany(Unit::class)
        ->where(function ($query) {
            $query->whereColumn('units.base_unit_id', '=', $this->qualifyColumn('unit_id'))
                ->orWhereColumn('units.id', '=', $this->qualifyColumn('unit_id'));
        });
}

逻辑说明

  • 关联条件自动匹配两类单位:
    • units.id = products.unit_id:产品直接绑定的基础单位
    • units.base_unit_id = products.unit_id:所有以当前产品基础单位为父单位的子单位
  • 用闭包包裹查询条件,避免orWhere破坏预加载自带的软删除、全局作用域等查询条件
  • 用whereColumn/orWhereColumn做表字段间的匹配,完全兼容预加载的批量查询逻辑,不需要依赖单个模型实例的属性,直接支持Product::with('units')->get()的写法
  • 最终返回的每个产品的units属性就是符合要求的单位集合,结构和预期一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 09:27:35