在Laravel开发文章管理相关功能时,我们经常会遇到需要同时筛选多个分类下的文章的需求,比如用户勾选了科技、教育、娱乐三个分类,需要返回这三个分类下的所有文章。这种场景下使用Eloquent的whereIn方法可以非常高效地实现需求,不需要编写复杂的SQL语句。

whereIn方法基本用法
whereIn是Laravel查询构造器提供的方法,用于判断指定字段的值是否在给定数组中,基本语法如下:
// 查询分类ID为1、2、3的文章
$articles = Article::whereIn('category_id', [1, 2, 3])->get();上面的代码会生成类似SELECT * FROM articles WHERE category_id IN (1,2,3)的SQL语句,匹配所有分类ID在给定数组中的文章记录。
多分类文章筛选实现步骤
1. 接收前端传递的分类参数
前端通常会通过查询参数传递多个分类ID,比如/articles?categories=1,2,3,后端需要先接收并处理好这个参数:
// 接收分类参数,默认是空数组
$categoryIds = request()->input('categories', '');
if (!empty($categoryIds)) {
// 将逗号分隔的字符串转为数组
$categoryIds = explode(',', $categoryIds);
// 过滤掉非数字的无效值
$categoryIds = array_filter($categoryIds, function ($id) {
return is_numeric($id);
});
} else {
$categoryIds = [];
}2. 构造查询条件
得到有效的分类ID数组后,就可以使用whereIn方法构造查询条件,同时可以结合其他查询条件实现更复杂的筛选:
$query = Article::query();
// 如果有传递分类ID,才添加whereIn条件
if (!empty($categoryIds)) {
$query->whereIn('category_id', $categoryIds);
}
// 可以添加其他查询条件,比如只查询已发布的文章
$query->where('status', 1);
// 按发布时间倒序排序
$query->orderBy('published_at', 'desc');
// 分页获取结果
$articles = $query->paginate(15);3. 关联分类表查询场景
如果文章和分类是多对多的关联关系,比如文章可以属于多个分类,需要通过中间表查询,也可以使用whereIn结合whereHas实现:
// 文章和分类是多对多关系,通过category_article中间表关联
$articles = Article::whereHas('categories', function ($query) use ($categoryIds) {
$query->whereIn('categories.id', $categoryIds);
})->get();使用注意事项
- 当传入的数组为空时,whereIn会生成
WHERE column IN ()的SQL片段,这是无效的SQL语法,所以一定要先判断数组是否为空,为空时不要添加该条件。 - 如果分类ID数组元素非常多,比如超过1000个,部分数据库会对IN语句的长度有限制,这种情况可以考虑分批查询或者使用whereRaw结合临时表实现。
- whereIn的第二个参数需要是数组类型,如果不是数组需要先转换,否则会抛出类型错误异常。
- 可以通过addBinding方法手动绑定参数,避免SQL注入风险,不过whereIn方法内部已经做了参数绑定,正常使用时不需要额外处理。
性能优化建议
如果多分类筛选的场景查询频率很高,可以给文章的category_id字段添加索引,提升IN查询的效率。如果是多对多关联查询的场景,可以给中间表的category_id和article_id字段分别添加索引,减少关联查询的耗时。
另外如果不需要查询所有字段,可以使用select方法指定需要的字段,减少查询返回的数据量,进一步提升查询性能。