Laravel 8集合返回错误ID,是框架BUG还是操作失误?
结论
这不是Laravel框架的BUG,属于PDO底层的默认行为,是查询写法的预期结果。
原因说明
当你执行JOIN查询同时使用*查询两个表的所有字段时,peoples表和companies表存在同名字段id,PHP底层的PDO扩展在返回结果集时,会将同名字段做覆盖处理:后查询的companies表的id值会覆盖先查询的peoples表的id值。
你在phpMyAdmin中查询结果正常,是因为phpMyAdmin在渲染结果时会自动加上表前缀区分同名字段,而原生PDO以及基于PDO封装的Laravel数据库操作层不会做自动区分,同名字段仅会保留最后出现的对应值。
推荐解决方案
除了你提到的手动指定必要字段的方案外,还有两种更易用的写法:
- 给同名字段加别名
如果需要保留两个表的所有字段,只需给同名字段单独指定别名即可避免覆盖:
$clients = People::select('peoples.*', 'companies.id as company_id', 'companies.*') ->join('companies', 'peoples.company_id', '=', 'companies.id') ->where('companies.is_active', '>', 0) ->orderBy('company') ->get();
- 使用Eloquent关联预加载(更推荐)
直接在People模型中定义关联关系,不用手动写JOIN,完全避免字段冲突问题:
首先在app/Models/People.php中定义关联:
public function company() { return $this->belongsTo(Company::class); }
查询时直接使用whereHas+with即可:
$clients = People::whereHas('company', function ($query) { $query->where('is_active', '>', 0); })->with('company')->orderBy('company.company')->get();
这种写法返回的结果中,人员自身的字段都在根层级,关联的公司数据会放在单独的company属性下,完全不会出现同名字段覆盖的问题。
内容的提问来源于stack exchange,提问作者Paul Godard
相关产品推荐
相关产品推荐

