Laravel 5.4 Eloquent关联查询使用->first()返回null问题求助
解决Laravel 5.4 Eloquent关联获取最新对话记录的问题
我来帮你分析下这个问题哈,你现在的写法有两个关键问题导致返回null,咱们一步步拆解:
问题出在哪?
with闭包里调用first()的错误:with是用来预加载每个Solicitud模型对应的关联数据,你在闭包里直接加first(),会让整个关联查询只执行一次、返回一条记录,而不是每个Solicitud对应的最新对话。这就导致大部分Solicitud的conversation关联变成null。groupBy和orderBy的执行顺序问题:MySQL中groupBy的执行逻辑是先分组再排序,你写的orderBy('created_at', 'DESC')->groupBy('solicitud'),实际是先按solicitud分组,每组取默认的第一条记录,再对这些记录排序,根本达不到“取每组最新记录”的效果。
正确的解决方案
方法一:定义专属的关联方法(最推荐)
在你的Solicitud模型里新增一个关联方法,专门用来获取最新的对话:
// app/Solicitud.php public function latestConversation() { // 假设Conversation模型的外键是solicitud,对应Solicitud的idSolicitud return $this->hasOne(Conversation::class, 'solicitud')->latest('created_at'); }
然后查询时直接用这个关联:
$chats = Solicitud::with(['reservation', 'detail.subDetails', 'latestConversation']) ->whereIn('idSolicitud', $r) ->skip($inicio) ->take($elementos) ->orderByRaw("field(idSolicitud, ".implode(', ' , $r->toArray()).")") ->get();
这样每个Solicitud都会自动关联到它对应的最新对话记录,代码也更清晰。
方法二:在with闭包里用子查询约束
如果不想新增关联方法,可以用子查询筛选出每个solicitud的最新对话ID,再关联查询:
use Illuminate\Support\Facades\DB; $chats = Solicitud::with(['reservation', 'detail.subDetails', 'conversation' => function($q) { $q->whereIn('id', function($subQuery) { $subQuery->select(DB::raw('MAX(id)')) ->from('conversations') ->groupBy('solicitud'); }); }]) ->whereIn('idSolicitud', $r) ->skip($inicio) ->take($elementos) ->orderByRaw("field(idSolicitud, ".implode(', ' , $r->toArray()).")") ->get();
这里假设conversations表的id是自增主键,那么MAX(id)对应的就是最新创建的记录。如果你的created_at可能和id不严格同步,可以改成按created_at取最大值再关联:
$q->whereRaw('(solicitud, created_at) IN (SELECT solicitud, MAX(created_at) FROM conversations GROUP BY solicitud)');
验证要点
- 确认
conversations表的solicitud字段确实关联到Solicitud表的idSolicitud(如果外键名不一致,要在关联方法里指定)。 - 检查有没有
Solicitud对应的conversations记录为空的情况,这种时候关联自然会返回null,属于正常现象。
内容的提问来源于stack exchange,提问作者Jorge Mejia
相关产品推荐
相关产品推荐

