Laravel Eloquent:belongsToMany关联取唯一值及三表关联问题
解决Laravel Eloquent三张表关联并获取唯一值的问题
嘿,我来帮你搞定这个关联问题!首先咱们先明确你的表结构:
t_orders:订单表,关联customer_idt_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
相关产品推荐
相关产品推荐

