
在 Laravel 中,若使用 new User() 初始化模型实例后进行链式查询(如 whereIn、with),会导致查询不生效或报错;正确做法是使用 User::query() 获取可链式调用的查询构建器实例。
在 laravel 中,若使用 `new user()` 初始化模型实例后进行链式查询(如 `wherein`、`with`),会导致查询不生效或报错;正确做法是使用 `user::query()` 获取可链式调用的查询构建器实例。
在 Laravel 的 Eloquent ORM 中,模型实例(new User())和查询构建器(User::query())具有本质区别:前者是一个数据模型对象,不具备查询能力;后者返回的是 Illuminate\Database\Eloquent\Builder 实例,专为链式构造 SQL 查询而设计。
你遇到的问题——$users->whereIn('id', $viewedIds) 无效果,随后 ->with('profile')->where(...)->simplePaginate() 仍作用于原始未过滤的数据集——正是因为 $users = new User() 创建的是一个空模型实例,其后续调用的 whereIn() 等方法不会累积到查询中,而是被静默忽略(或触发不可预期行为),最终 simplePaginate() 执行的是一个未经 whereIn 约束的基础查询。
✅ 正确写法如下:
// ✅ 推荐:从查询构建器开始构建
$users = User::query();
// 可安全、可中断、可复用地链式添加约束
$users->whereIn('id', $viewedIds);
$users->with('profile');
$users->where('gender', $searchGender);
$users->orderBy('last_login');
$rdata = $users->simplePaginate(8);⚠️ 注意事项:
- ❌ new User() 返回的是模型实例,不是查询构建器,不能用于构造查询;
- ✅ User::query() 是获取 Builder 实例的标准且唯一推荐方式;
- 链式调用中,with() 应尽量前置(避免 N+1),但位置不影响 where 类约束的生效逻辑;
- 若需动态拼接条件(例如根据表单请求决定是否添加 whereIn),可安全地在 query() 后分步调用,无需担心“丢失上下文”。
? 进阶提示:你也可以将逻辑封装为作用域(Local Scope)提升可维护性:
// 在 User 模型中定义
public function scopeFilteredByViewedAndGender($query, array $viewedIds, string $gender)
{
return $query->whereIn('id', $viewedIds)
->where('gender', $gender)
->with('profile')
->orderBy('last_login');
}
// 使用时
$rdata = User::query()
->filteredByViewedAndGender($viewedIds, $searchGender)
->simplePaginate(8);总之,牢记:所有链式 Eloquent 查询必须始于 Model::query(),而非 new Model()。这是保障查询逻辑可预测、可调试、可扩展的基础前提。










