脱离Laravel框架使用Eloquent ORM时,如何获取查询执行的SQL语句?
如何在独立使用Eloquent ORM时获取执行的SQL语句
嘿,我完全懂你遇到的困惑——单独用Eloquent而不是Laravel框架的时候,想拿到get()执行的SQL确实容易踩坑,毕竟toSql()并不是Model实例或者Collection对象的方法,它属于QueryBuilder(查询构建器)。咱们分几种情况来解决:
一、执行查询前获取SQL
在调用get()之前,你调用的orderBy()(还有where()、select()这类方法)都会返回一个QueryBuilder实例,这时候还没真正执行数据库查询,直接调用toSql()就能拿到拼接好的SQL了:
// $this->hmisUsers 是HmisUsers表的Model实例 $hmisModel = $this->hmisUsers; // 先获取QueryBuilder对象,此时还未执行查询 $query = $hmisModel->orderBy('UserName'); // 打印生成的SQL语句 echo $query->toSql(); // 再执行查询获取Collection $hmisUsers = $query->get();
二、已经执行查询后获取SQL
如果已经调用get()得到了Collection对象,也不用慌,Collection内部保留了对应的查询构建器实例,你可以通过query属性拿到它,再调用toSql():
$hmisUsers = $hmisModel->orderBy('UserName')->get(); // 从Collection中提取原始查询的SQL echo $hmisUsers->query->toSql();
三、获取带真实参数的完整SQL
注意toSql()返回的SQL里参数是用?占位的(Eloquent用参数绑定防SQL注入),如果想看到实际执行时带真实参数的SQL,可以结合getBindings()方法手动替换占位符:
$query = $hmisModel->orderBy('UserName'); // 获取基础SQL和绑定参数 $sql = $query->toSql(); $bindings = $query->getBindings(); // 替换占位符,生成可直接执行的完整SQL $fullSql = str_replace('?', '%s', $sql); $fullSql = vsprintf($fullSql, array_map(function ($binding) { // 字符串参数加引号,数字直接保留 return is_string($binding) ? "'{$binding}'" : $binding; }, $bindings)); echo $fullSql;
四、全局监听所有查询(适合批量诊断)
如果你需要监控所有Eloquent执行的查询,可以注册一个查询事件监听器,这样每次查询执行都会自动输出SQL和执行时间:
use Illuminate\Database\Events\QueryExecuted; use Illuminate\Support\Facades\Event; // 注册查询执行事件监听 Event::listen(QueryExecuted::class, function (QueryExecuted $event) { $sql = $event->sql; $bindings = $event->bindings; $executionTime = $event->time; // 查询耗时,单位毫秒 // 生成带真实参数的完整SQL $fullSql = str_replace('?', '%s', $sql); $fullSql = vsprintf($fullSql, array_map(function ($binding) { return is_string($binding) ? "'{$binding}'" : $binding; }, $bindings)); // 输出诊断信息 echo "执行SQL:{$fullSql} | 耗时:{$executionTime}ms\n"; });
内容的提问来源于stack exchange,提问作者RyanNerd
相关产品推荐
相关产品推荐

