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

Laravel Eloquent:belongsToMany关联取唯一值及三表关联问题

解决Laravel Eloquent三张表关联并获取唯一值的问题

嘿,我来帮你搞定这个关联问题!首先咱们先明确你的表结构:

  • t_orders:订单表,关联customer_id
  • t_orders_items:订单项表,记录每个订单对应的fabrication_order
  • 隐含的客户表(比如t_customers,因为t_orders有customer_id字段)

下面分场景给你梳理关联方式和获取唯一值的方法:

1. 基础模型定义

先把三个核心模型创建好,确保基础关联逻辑正确:

Customer 模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{
    protected $table = 't_customers'; // 替换成你的客户表实际名称
    protected $primaryKey = 'customer_id';

    // 关联该客户的所有订单
    public function orders()
    {
        return $this->hasMany(Order::class, 'customer_id');
    }
}

Order 模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    protected $table = 't_orders';
    protected $primaryKey = 'order_id';

    // 关联所属客户
    public function customer()
    {
        return $this->belongsTo(Customer::class, 'customer_id');
    }

    // 关联该订单的所有订单项
    public function orderItems()
    {
        return $this->hasMany(OrderItem::class, 'order_id');
    }
}

OrderItem 模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class OrderItem extends Model
{
    protected $table = 't_orders_items';
    public $timestamps = false; // 如果表没有created_at/updated_at字段,一定要加这个

    // 关联所属订单
    public function order()
    {
        return $this->belongsTo(Order::class, 'order_id');
    }
}

2. 场景一:获取单个订单的唯一fabrication_order值

如果只是想拿到某一个订单下不重复的fabrication_order,直接在Order模型里新增一个关联方法:

// 在Order模型中添加
public function uniqueFabricationOrders()
{
    return $this->orderItems()
        ->select('fabrication_order')
        ->distinct(); // 关键:去重获取唯一值
}

使用方式:

$order = Order::find(1);
// 获取唯一值数组
$uniqueFabOrders = $order->uniqueFabricationOrders()->pluck('fabrication_order');

3. 场景二:获取某客户所有订单的唯一fabrication_order值

如果要从客户维度,拿到该客户所有订单里的不重复fabrication_order,有两种实用方式:

方式一:使用belongsToMany + through关联(推荐)

如果你的fabrication_order对应一个单独的业务表(比如t_fabrication_orders),可以用这种关联方式:

首先创建FabricationOrder模型:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class FabricationOrder extends Model
{
    protected $table = 't_fabrication_orders';
    protected $primaryKey = 'fabrication_order'; // 假设主键就是这个字段
}

然后在Customer模型里添加关联:

// 在Customer模型中添加
public function uniqueFabricationOrders()
{
    return $this->belongsToMany(
        FabricationOrder::class,
        't_orders_items', // 中间表
        'order_id', // 中间表关联Order的外键
        'fabrication_order' // 中间表关联FabricationOrder的外键
    )->through(Order::class) // 通过Order表关联
      ->distinct(); // 去重
}

使用方式:

$customer = Customer::find(5);
// 获取唯一的FabricationOrder模型集合
$uniqueFabOrders = $customer->uniqueFabricationOrders;

方式二:直接用查询构建器获取值数组

如果不需要FabricationOrder模型,只想拿到纯值数组,直接写查询逻辑即可:

$customer = Customer::find(5);
$uniqueFabOrders = $customer->orders()
    ->join('t_orders_items', 't_orders.order_id', '=', 't_orders_items.order_id')
    ->select('t_orders_items.fabrication_order')
    ->distinct()
    ->pluck('fabrication_order');

也可以把这个逻辑封装成Customer模型的访问器,方便调用:

// 在Customer模型中添加
public function getUniqueFabricationOrdersAttribute()
{
    return $this->orders()
        ->join('t_orders_items', 't_orders.order_id', '=', 't_orders_items.order_id')
        ->select('t_orders_items.fabrication_order')
        ->distinct()
        ->pluck('fabrication_order');
}

使用方式:

$customer = Customer::find(5);
$uniqueFabOrders = $customer->unique_fabrication_orders; // 自动触发访问器

关键注意点

  • 确保所有模型的$table、$primaryKey配置和数据库表结构完全对应
  • 如果表没有时间戳字段,一定要在模型里设置public $timestamps = false;,避免Eloquent自动尝试更新不存在的字段
  • distinct()是实现“唯一值”的核心,一定要加上,否则会返回重复条目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:40:26