Laravel Admin角色文件过滤器因重复ID报HY093错误求助
问题
在Laravel应用中为管理员、合作伙伴角色开发文件字段过滤器,合作伙伴端可正常显示权限范围内的文件,但管理员端访问全部文件时报错:
SQLSTATE[HY093]: Invalid parameter number SQL: select * from `file` where `id` in (9, 11, 9, 11, 9, 11, 9, 11, 9, 11)
直接在数据库执行该SQL可正常运行,但Laravel中报错,求解决方法。
管理员端过滤器代码
if ($tag_id != 0 && $langs != 0) { for ($i = 0; $i < $count; $i++) { $fileCount = File_Tag::where('tag_id', $tag_id)->pluck('file_id')->count(); $file[] = $fileCount > 0 ? File_Tag::where('tag_id', $tag_id)->pluck('file_id') : null; } $this->AdminFiles = File::whereIn('id', $file)->where('language_id', $langs)->get(); } else if ($tag_id != 0) { for ($i = 0; $i < $count; $i++) { $fileCount = File_Tag::where('tag_id', $tag_id)->pluck('file_id')->count(); $file[] = $fileCount > 0 ? File_Tag::where('tag_id', $tag_id)->pluck('file_id') : null; } $this->AdminFiles = File::whereIn('id', $file)->get(); } else if ($langs != 0) { $this->files = File::where('language_id', $langs)->get(); } else { $this->AdminFiles = File::all(); }
合作伙伴端过滤器代码(正常运行)
if($tag_id != 0 && $langs != 0) { for ($i = 0; $i < count($file_role); $i++) { $fileCount = File_Tag::where('tag_id', $tag_id)->where('file_id', '=', $file_role[$i])->pluck('file_id')->count(); $file[] = $fileCount > 0 ? File_Tag::where('tag_id', $tag_id)->where('file_id', '=', $file_role[$i])->pluck('file_id') : null; } $this->files = File::whereIn('id', $file)->where('language_id', $langs)->get(); } else if ($tag_id != 0) { for ($i = 0; $i < count($file_role); $i++) { $fileCount = File_Tag::where('tag_id', $tag_id)->where('file_id', '=', $file_role[$i])->pluck('file_id')->count(); $file[] = $fileCount > 0 ? File_Tag::where('tag_id', $tag_id)->where('file_id', '=', $file_role[$i])->pluck('file_id') : null; } $this->files = File::whereIn('id', $file)->get(); } else if($langs != 0) { $this->files = File::whereIn('id', $file_role)->where('language_id', $langs)->get(); } else { $this->files = File::whereIn('id',$file_role)->get(); }
解决方法
问题根源:管理员代码里的
$file是二维数组(pluck('file_id')返回集合/数组,循环多次后嵌套),而Laravel的whereIn要求传入一维数组;同时循环重复插入导致ID重复,进一步触发参数绑定异常。修复方案:
- 移除冗余循环:管理员无需循环
$count次,一次查询即可获取所有关联的file_id。 - 处理数组格式:将查询结果转为一维数组并去重,适配
whereIn要求。 - 优化查询性能:避免多次重复查询数据库,减少不必要的IO开销。
- 移除冗余循环:管理员无需循环
优化后的管理员端代码:
if ($tag_id != 0 && $langs != 0) { // 一次查询拿到所有关联file_id,转一维数组并去重 $fileIds = File_Tag::where('tag_id', $tag_id)->pluck('file_id')->unique()->toArray(); $this->AdminFiles = File::whereIn('id', $fileIds)->where('language_id', $langs)->get(); } else if ($tag_id != 0) { $fileIds = File_Tag::where('tag_id', $tag_id)->pluck('file_id')->unique()->toArray(); $this->AdminFiles = File::whereIn('id', $fileIds)->get(); } else if ($langs != 0) { $this->files = File::where('language_id', $langs)->get(); } else { $this->AdminFiles = File::all(); }
- 进阶优化建议:给
File模型添加关联方法,进一步简化查询逻辑:
在File模型中定义关联:
public function tags() { return $this->belongsToMany(Tag::class, 'file_tag', 'file_id', 'tag_id'); }
之后管理员查询可简化为:
$this->AdminFiles = File::whereHas('tags', function ($query) use ($tag_id) { $query->where('id', $tag_id); })->when($langs != 0, function ($query) use ($langs) { $query->where('language_id', $langs); })->get();
内容的提问来源于stack exchange,提问作者Delano van londen
相关产品推荐
相关产品推荐

