为何Laravel Eloquent查询中$id变为布尔值?
问题成因及修复方案
核心问题1:when闭包的参数误解
Laravel的when方法回调函数的第二个参数是条件的布尔值,不是你自定义的变量。你在每个when的闭包里都声明了function ($query, $id),这里的$id会覆盖外部的路由参数$id,被赋值成when第一个参数(比如request()->hasAny(...))的返回结果——也就是布尔值true,这就是闭包内$id变成boolean的根本原因。
核心问题2:错误调用query()方法
Product::query($id)是错误用法,Laravel的query()方法不需要传递模型ID作为参数,它仅用于创建查询构造器实例,你传入的$id会被当成可选的$columns数组参数,根本无法实现collection_id的过滤逻辑。
修复步骤
- 修正基础查询逻辑:先添加
collection_id的过滤条件,替换错误的query($id)调用:
Product::query()->where('collection_id', $id)
- 移除闭包内的冗余
$id参数:所有when的回调仅保留$query参数,闭包可直接使用外部的$id变量(PHP闭包默认继承外部作用域变量,无需额外传参):
->when(request()->hasAny('length78', 'length34', 'lengthBl', 'lengthS', 'lengthN' ), function ($query) { // 直接使用外部的$id,无需作为参数传入 // ... 原有筛选逻辑 })
- 优化查询分组(避免逻辑冲突):多个
orWhere需要用子查询闭包包住,否则会和collection_id的where条件产生逻辑错误(比如会变成collection_id=? OR length=?,而非预期的collection_id=? AND (length=? OR length=?)):
->when(request()->hasAny('length78', 'length34', 'lengthBl', 'lengthS', 'lengthN' ), function ($query) { $query->where(function($subQuery) { if(request()->input('length78') === "true"){ $subQuery->orWhere('length', '=', '7/8'); } // 其他长度判断逻辑... }); })
完整修复后的代码
public function collection($id) { return Inertia::render('Collection', [ 'products' => Product::query() ->where('collection_id', $id) ->when(request()->hasAny('length78', 'length34', 'lengthBl', 'lengthS', 'lengthN' ), function ($query) { $query->where(function($subQuery) { if(request()->input('length78') === "true"){ $subQuery->orWhere('length', '=', '7/8'); } if(request()->input('length34') === "true"){ $subQuery->orWhere('length', '=', '3/4'); } if(request()->input('lengthBl') === "true"){ $subQuery->orWhere('length', '=', 'bicycle length'); } if(request()->input('lengthS') === "true"){ $subQuery->orWhere('length', '=', 'short'); } if(request()->input('lengthN') === "true"){ $subQuery->orWhere('length', '=', 'normal'); } }); }) ->when(request()->hasAny('blue', 'beige', 'grey', 'military', 'pink', 'black'), function ($query) { $query->where(function($subQuery) { if(request()->input('blue') === "true"){ $subQuery->orWhere('color', '=', 'blue'); } if(request()->input('beige') === "true"){ $subQuery->orWhere('color', '=', 'beige'); } if(request()->input('grey') === "true"){ $subQuery->orWhere('color', '=', 'grey'); } if(request()->input('military') === "true"){ $subQuery->orWhere('color', '=', 'military'); } if(request()->input('pink') === "true"){ $subQuery->orWhere('color', '=', 'pink'); } if(request()->input('black') === "true"){ $subQuery->orWhere('color', '=', 'black'); } }); }) ->when(request()->has('vMin'), function ($query) { $query->where('price', '>=', request()->input('vMin')); }) ->when(request()->has('vMax'), function ($query) { $query->where('price', '<=', request()->input('vMax')); }) ->paginate(10) ->withQueryString() ->through(fn($product) => [ 'id' => $product->id, 'name' => $product->name, 'size' => $product->size, 'waist' => $product->size, 'price' => $product->price, 'collection_id' => $product->collection_id, 'description' => $product->description ]), 'filters' => (new \Illuminate\Http\Request)->only([ 'sizeXxs', 'sizeXs', 'sizeS', 'sizeM', 'sizeL', 'sizeXl', 'filters', 'waistM', 'waistH', 'waistHi', 'collection', 'length78', 'length34', 'lengthBl', 'lengthS', 'lengthN', 'vMin', 'vMax', 'blue', 'beige', 'grey', 'military', 'pink', 'black' ]) ]); }
内容的提问来源于stack exchange,提问作者vStubbs
相关产品推荐
相关产品推荐

