Laravel关联查询中如何使用whereHas实现多流派AND条件筛选动画作品
解决方案
问题根源
你当前写法中的whereHas搭配whereIn,仅判断动画关联的流派是否存在任意一个在选中列表内,自然是OR逻辑,无法满足同时匹配所有选中流派的需求。
最优修改方案
直接利用Laravel whereHas 方法的计数参数即可实现需求,仅需要修改流派筛选部分的逻辑:
if($request->genres){ // 先对传入的流派ID去重,避免重复值导致计数错误 $genres = array_unique($request->genres ?? []); if (!empty($genres)) { $anime->whereHas('genres', function($q) use($genres){ $q->whereIn('id', $genres); }, '=', count($genres)); } }
逻辑说明
whereHas 第三个和第四个参数的作用是:要求关联表中符合条件的记录数量等于传入的选中流派总数。也就是说如果用户选了3个流派,那么该动画的关联流派中必须同时存在这3个,满足条件的关联记录数才会等于3,符合筛选要求,完美实现AND逻辑。
兼容备选方案
如果使用的Laravel版本过低不支持上述计数参数,也可以通过循环叠加whereHas实现,只是选中流派较多时性能略低于上面的方案:
if($request->genres){ $genres = array_unique($request->genres ?? []); foreach ($genres as $genreId) { $anime->whereHas('genres', function($q) use ($genreId) { $q->where('id', $genreId); }); } }
完整修改后代码
$anime = AnimeShow::select('id', 'slug', 'status', 'title_eng', 'title_jap', 'description', 'episodes', 'premier_date', 'status') ->with('media:anime_show_id,image_path'); if($request->genres){ $genres = array_unique($request->genres ?? []); if (!empty($genres)) { $anime->whereHas('genres', function($q) use($genres){ $q->whereIn('id', $genres); }, '=', count($genres)); } } if($request->airing){ $anime->whereIn('status', $request->airing); } $anime->search($request->search); return response($anime->paginate($request->perPage, ['*'], 'page', $request->currentPage));
内容的提问来源于stack exchange,提问作者Beusebiu
相关产品推荐
相关产品推荐

