Laravel 5.7能否基于逗号分隔ID列建立Eloquent模型关联?
在Laravel 5.7中基于逗号分隔ID列实现Eloquent关联
嘿,这个需求完全可以实现!虽然Laravel默认的Eloquent关联都是基于标准外键设计的,但针对你这种存在逗号分隔ID的场景,我们可以通过数据库函数结合自定义关联方法来搞定,不用额外写get/set方法就能让关联自动生效。
实现HasMany关联(多ID对应多个模型)
假设你有一个主模型(比如Order),driver_id列存的是逗号分隔的司机ID,关联的司机模型是Driver。你可以在Order模型里定义这样的关联方法:
public function drivers() { return $this->hasMany(Driver::class) ->whereRaw("FIND_IN_SET(id, ?)", [$this->driver_id]); }
这里用到了MySQL的FIND_IN_SET函数,它会在逗号分隔的字符串里匹配指定的ID值,相当于把你的driver_id列拆分成多个ID来关联对应的Driver模型。定义好之后,你就能像用普通HasMany关联一样使用它:
- 直接调用:
$order->drivers会返回所有匹配的司机模型集合 - 预加载:
Order::with('drivers')->get()批量查询时也能正常加载关联数据
实现HasOne关联(取第一个匹配的模型)
如果你的场景只需要关联其中一个司机(比如第一个ID对应的),可以调整成HasOne关联,同时用FIELD函数保证顺序:
public function primaryDriver() { return $this->hasOne(Driver::class) ->whereRaw("FIND_IN_SET(id, ?)", [$this->driver_id]) ->orderByRaw("FIELD(id, ?)", [$this->driver_id]); }
这样$order->primaryDriver就会返回driver_id列中第一个ID对应的司机模型。
注意事项
虽然这种方法能满足你的需求,但还是要提醒一句:这种逗号分隔ID的设计并不符合数据库规范化原则,当数据量较大时,FIND_IN_SET无法利用索引,会导致查询性能下降。如果项目还有优化空间,建议改成多对多的中间表结构(比如order_driver表),这才是Laravel推荐的关联方式。
内容的提问来源于stack exchange,提问作者pankaj
相关产品推荐
相关产品推荐

