You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

额外优化建议

  1. 简化models收集逻辑:
    原循环去重的代码可以替换为一行:
    $models = Scandal::pluck('modelo')->unique()->toArray();
    
  2. 移除无用变量:$borrado变量未被使用,可直接删除或补全赋值。
  3. 严谨判断请求参数:用$request->filled('字段名')替代$request['字段'],会自动排除空字符串、null等无效值。

内容的提问来源于stack exchange,提问作者Peisou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 09:40:36