Laravel条件式预加载:如何按model_type控制关联加载?
解决方案
你可以通过延迟加载关联的方式,先获取所有符合条件的分页记录,再针对model_type为campaign_channel_rule的子集加载关联关系,这样campaign类型的记录就不会触发关联查询。
代码实现
$paginated = File::whereIn('model_id', $channelRules->pluck('id')) ->where('model_type', 'campaign_channel_rule') ->orWhere(function($query) use($campaign) { $query->where('model_type', 'campaign')->where('model_id', $campaign->id); }) ->paginate(15); // 仅对model_type为campaign_channel_rule的文件加载关联 $paginated->getCollection() ->where('model_type', 'campaign_channel_rule') ->load('campaignChannelRule.channel.channel');
原理说明
- 先执行主查询获取所有符合条件的分页记录,此时不会预加载任何关联。
- 从分页结果的集合中筛选出
model_type为campaign_channel_rule的记录,调用load()方法延迟加载指定关联。 campaign类型的记录不会执行关联查询,完全符合你的需求。
备选方案:分查询合并分页
如果需要严格分开两次查询(比如关联查询条件复杂),可以分别查询两种类型的记录,合并后手动创建分页器:
// 查询带关联的campaign_channel_rule类型文件 $channelRuleFiles = File::whereIn('model_id', $channelRules->pluck('id')) ->where('model_type', 'campaign_channel_rule') ->with('campaignChannelRule.channel.channel') ->get(); // 查询不带关联的campaign类型文件 $campaignFiles = File::where('model_type', 'campaign') ->where('model_id', $campaign->id) ->get(); // 合并集合 $allFiles = $channelRuleFiles->merge($campaignFiles); // 手动创建分页器 $perPage = 15; $currentPage = request()->get('page', 1); $paginatedFiles = new \Illuminate\Pagination\LengthAwarePaginator( $allFiles->forPage($currentPage, $perPage), $allFiles->count(), $perPage, $currentPage, ['path' => request()->url(), 'query' => request()->query()] );
内容的提问来源于stack exchange,提问作者Jenssen
相关产品推荐
相关产品推荐

