Laravel中根据参数添加次级查询遇Eloquent Builder属性不存在错误
问题描述
我正尝试根据表单输入字段构建复杂查询,代码如下:
public function search(Request $request){ $borrado = $activo = 0; $models = array(); $escandallos = Scandal::all(); foreach ($escandallos as $escandallo){ if (in_array($escandallo->modelo, $models)) { }else{ array_push($models, $escandallo->modelo); } } $query = Model::where('modelo', 'like', '%' . $request['modelo'] . '%') ->where('prototipo', 'like', '%' . $request['prototipo'] . '%') ->where('oficial', 'like', '%' . $request['modofi'] . '%') ->where('usuario_realiza', 'like', '%' . $request['usuario'] . '%') ->where('tipo', 'like', '%' . $request['tipo'] . '%') ->where('activa', 'like', '%' . $activo . '%'); if($request['referencia'] || $request['proveedor']){ /** 当请求中存在referencia或proveedor时,需要关联其他表做where in子查询 */ $query->DB::raw("where (id_escandallo,id_version) in (select id_escandallo,id_version from escandallo_p where referencia ='" . $request['referencia'] . "' and proveedor ='" . $request['proveedor'] . "'"); } $query->orderBy('modelo','desc'); $query->orderBy('id_version','asc'); $scandals = $query->paginate(100); dd($scandals); return view('designdoc.escandallos',['scandals'=> $scandals],['models'=>$models]); }
运行后返回错误:
Property [DB] does not exist on the Eloquent builder instance.
我的需求是当请求中存在referencia或proveedor参数时,通过DB::raw添加where in子句关联其他表查询,如何解决?
解决方案
错误原因
你错误地在Eloquent查询构建器实例上调用了DB::raw()——DB是Laravel的全局门面,不能通过查询构建器对象($query)调用,这才触发了"Property [DB] does not exist"的错误。此外代码还存在SQL注入风险,以及子查询语法不完整(缺少闭合括号)的问题。
修正代码
推荐使用参数绑定避免SQL注入,同时调整多列IN查询的写法,以下是两种可行方案:
方案一:利用Eloquent子查询(更优雅)
if($request->filled('referencia') || $request->filled('proveedor')){ // 构建子查询 $subQuery = EscandalloP::select('id_escandallo', 'id_version'); if($request->filled('referencia')){ $subQuery->where('referencia', $request->referencia); } if($request->filled('proveedor')){ $subQuery->where('proveedor', $request->proveedor); } // 绑定子查询到主查询 $query->whereRaw('(id_escandallo, id_version) in (' . $subQuery->toSql() . ')', $subQuery->getBindings()); }
方案二:使用DB::raw配合参数绑定
if($request->filled('referencia') || $request->filled('proveedor')){ $sqlConditions = []; $bindings = []; // 按需拼接条件 if($request->filled('referencia')){ $sqlConditions[] = 'referencia = ?'; $bindings[] = $request->referencia; } if($request->filled('proveedor')){ $sqlConditions[] = 'proveedor = ?'; $bindings[] = $request->proveedor; } $whereClause = implode(' AND ', $sqlConditions); // 用where方法传入DB::raw语句和绑定参数 $query->where(DB::raw("(id_escandallo, id_version) IN (SELECT id_escandallo, id_version FROM escandallo_p WHERE $whereClause)"), $bindings); }
额外优化建议
- 简化models收集逻辑:
原循环去重的代码可以替换为一行:$models = Scandal::pluck('modelo')->unique()->toArray(); - 移除无用变量:
$borrado变量未被使用,可直接删除或补全赋值。 - 严谨判断请求参数:用
$request->filled('字段名')替代$request['字段'],会自动排除空字符串、null等无效值。
内容的提问来源于stack exchange,提问作者Peisou
相关产品推荐
相关产品推荐

