Laravel Eloquent中如何关联两张表并合并为单表查询?
搞定Laravel Eloquent关联与合并查询的正确姿势
首先咱们先把你的模型关联给修正对,毕竟这是查询的基础:
1. 修正模型关联定义
先吐槽下你的模型命名(Laravel规范里类名首字母要大写哦),然后重点是要明确外键和本地键的对应关系——你的base_info表用的是baseId作为关联标识,而basecounts表用的是base_id,这俩命名风格不一样,必须手动指定,不然Eloquent会自动用默认规则(比如base_id对应Base模型的id字段),肯定查不对。
Base模型(对应base_info表)
class Base extends Model { // 指定表名(如果你的表名是带空格的base info,赶紧改成下划线格式base_info,数据库表名别用空格!) protected $table = 'base_info'; // 关联统计信息:一个基础信息对应一条统计数据(一对一关系) public function countInfo() { // 参数依次是:关联模型类、关联表的外键、当前模型的本地键 return $this->hasOne(CountInBase::class, 'base_id', 'baseId'); } }
CountInBase模型(对应basecounts表)
class CountInBase extends Model { protected $table = 'basecounts'; // 关联基础信息:统计数据属于某条基础信息(反向一对一) public function base() { return $this->belongsTo(Base::class, 'base_id', 'baseId'); } }
2. 两种方式实现"合并表"查询
方式一:用Eloquent关联预加载(推荐,符合ORM风格)
这种方式会先查基础信息表,再批量查对应的统计数据,避免N+1查询问题,结果里每个Base对象会带一个countInfo属性,包含统计字段:
// 获取所有基础信息及其对应的统计数据 $mergedData = Base::with('countInfo')->get(); // 遍历使用,比如输出地址和First统计值 foreach ($mergedData as $item) { echo "地址:{$item->address},First统计:{$item->countInfo->First}"; }
如果担心有些基础信息没有对应的统计数据会报错,可以给关联加withDefault()设置默认值:
public function countInfo() { return $this->hasOne(CountInBase::class, 'base_id', 'baseId')->withDefault([ 'First' => 0, 'Second' => 0, 'third' => 0, ]); }
方式二:用SQL JOIN直接合并字段(更像传统SQL查询)
如果你想把两个表的字段直接合并成一个结果集,就用leftJoin,这样查询出来的每个对象同时包含两张表的所有字段:
$mergedData = Base::select('base_info.*', 'basecounts.First', 'basecounts.Second', 'basecounts.third') ->leftJoin('basecounts', 'base_info.baseId', '=', 'basecounts.base_id') ->get(); // 直接访问合并后的字段 foreach ($mergedData as $item) { echo "地区:{$item->region},Third统计:{$item->third}"; }
内容的提问来源于stack exchange,提问作者jihad ismail
相关产品推荐
相关产品推荐

