Laravel 6.20调用toSql()获取SQL提示方法不存在咨询
报错原因
报错的核心是toSql()方法的调用对象错误:
- 代码中在
Car::where($criteria)后链式调用了->get(['id']),get()是查询执行方法,调用后会直接向数据库发起请求,返回Illuminate\Database\Eloquent\Collection集合实例,后续的->shuffle()是对内存中集合数据做随机排序的集合方法,此时$query存储的是已经查询完成的结果集合,不是待执行的查询构建器实例。 toSql()是查询构建器(Eloquent Builder/Query Builder)独有的方法,集合类未提供该方法,因此触发方法不存在的报错。- 额外说明:
shuffle()是PHP层面的集合操作,不会生成SQL语句,对应逻辑完全在服务端内存中完成,不存在对应的数据库查询语句。
正确获取SQL语句的方式
所有查询执行方法(get()/first()/paginate()等)以及后续的集合处理方法,必须在获取完SQL信息之后再调用,不能在取SQL前提前执行查询。
方法1:直接调用构建器的toSql方法
在调用执行方法前,基于查询构建器实例获取SQL,注意原生toSql()返回的是带?占位符的预处理SQL,可配合获取绑定参数得到完整信息:
// 构建查询,此时返回Eloquent查询构建器实例 $builder = Car::where($criteria); // 获取带占位符的SQL $sql = $builder->toSql(); // 获取SQL绑定的参数 $bindings = $builder->getBindings(); // 执行原有查询逻辑 $result = $builder->get(['id'])->shuffle(); // 记录日志 Log::info('查询信息', compact('sql', 'bindings'));
方法2:通过查询日志获取完整执行SQL
开启框架自带的查询日志,执行完查询后直接取出实际运行的SQL信息,不需要手动拼接参数,该方法在Laravel 6.20版本中可直接使用:
// 开启查询日志 DB::enableQueryLog(); // 执行原有查询逻辑 $result = Car::where($criteria)->get(['id'])->shuffle(); // 获取当前请求里所有执行过的SQL日志,包含完整SQL、绑定参数、执行耗时 $queries = DB::getQueryLog(); // 记录日志 Log::info($queries);
内容的提问来源于stack exchange,提问作者Murata
相关产品推荐
相关产品推荐

