Laravel 关联查询返回错误的 id

(本文原文地址:https://blog.tanteng.me/2017/03/laravel-mo...
在 Laravel Eloquent 中使用 join 关联查询,如果两张表有名称相同的字段,如 id,那么它的值会默认被后来的同名字段重写,返回不是期望的结果。例如以下关联查询:

$priority = Priority::rightJoin('touch', 'priorities.touch_id', '=', 'touch.id')
    ->where('priorities.type', 1)
    ->orderBy('priorities.total_score', 'desc')
    ->orderBy('touch.created_at', 'desc')
    ->get();

priorities 和 touch 这两张表都有 id 字段,如果这样构造查询的话,返回的查询结果如图:

wrong-id
这里 id 的值不是 priorities 表的 id 字段,而是 touch 表的 id 字段,如果打印出执行的 sql 语句:

select * from `priorities` 
right join `touch` 
on `priorities`.`touch_id` = `touch`.`id` 
where `priorities`.`type` = '1' 
order by `priorities`.`total_score` desc, `touch`.`created_at` desc

查询结果如图:
wrong-id
使用 sql 查询的结果实际上是对的,另外一张表重名的 id 字段被默认命名为 id1,但是 Laravel 返回的 id 的值却不是图中的 id 字段,而是被重名的另外一张表的字段重写了。

解决办法是加一个 select 方法指定字段,正确的构造查询语句的代码:

$priority = Priority::select(['priorities.*', 'touch.name', 'touch.add_user'])
    ->rightJoin('touch', 'priorities.touch_id', '=', 'touch.id')
    ->where('priorities.type', 1)
    ->orderBy('priorities.total_score', 'desc')
    ->orderBy('touch.created_at', 'desc')
    ->get();

这样就解决了问题,那么以后就要注意了,Laravel 两张表 join 的时候返回的字段最好要指定。

这算不算是 Laravel 的一个 bug 呢?如果一个字段的值被同名的字段值重写了,这种情况要不要报一个错误出来,而不能默认继续执行下去。

github 上有人也提出了同样的问题,作者也提供了解决办法,但并没其他更好的方案。

Laravel 版本:5.3

链接:https://github.com/laravel/framework/issue...

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1

这应该是 mysql 或 mysql 客户端的锅,用 PDO 貌似也会覆盖。写 sql 最好还是指定,或者用 AS 重命名。

7年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!