在Laravel Eloquent中能否同时使用with和cursor方法?
问题根因
Laravel的cursor()方法返回的是LazyCollection,会逐行从数据库获取单条模型实例,默认不会触发with()定义的关联预加载逻辑,所以直接在cursor()后操作模型时,关联数据不会被提前加载。
解决方案(按优先级排序)
1. 过滤逻辑下沉到SQL查询层(性能最优)
你示例中的ID过滤完全可以直接写在查询条件中,此时with()预加载会正常生效:
$chats = Items::with('users')->where('id', '>', 100)->cursor();
这种写法会先执行主表查询筛选符合id>100的记录,再执行关联预加载查询获取对应users数据,最后通过游标逐行返回带关联数据的模型实例,同时兼顾内存优化和预加载效果。
2. 过滤逻辑无法下沉到SQL的方案
如果你的过滤逻辑必须基于模型实例操作(比如需要调用模型自定义方法判断、处理访问器结果等),可以分两步实现:
// 第一步仅查询主表数据,筛选得到符合条件的记录ID $validItemIds = Items::cursor() ->filter(function ($item) { // 这里放你需要的复杂过滤逻辑 return $item->id > 100; }) ->pluck('id'); // 第二步基于筛选出的ID做预加载查询,再用游标返回 $chats = Items::with('users')->whereIn('id', $validItemIds)->cursor();
3. 数据量较小时的简化方案
如果你的表数据量不大,不需要游标来优化内存占用,可以直接用get()替代cursor(),预加载会直接生效:
$chats = Items::with('users') ->get() ->filter(function ($item) { return $item->id > 100; });
内容的提问来源于stack exchange,提问作者user10185524
相关产品推荐
相关产品推荐

