引言
在程序开发阶段,我们关注于业务逻辑,实现功能。而laravel提供了非常好的 debug 支持,只需在 env 文件内指定 debug = true ,就可以在页面打开 debug bar 用于调试。
其中也包含有Query选项,列出了程序加载流程中所有调用的SQL语句,这非常方便。
如果在没有debug,或者没有 blade 模板渲染的页面,如何获取 ORM 组装出来的SQL语句呢?
学习时间
比如有一个原始的查询:
DB::table("users")->get();
它生成的SQL语句是
SELECT * FROM users
那么在程序上下文中,应该如何获取并打印这个SQL语句呢。我们需要使用框架提供的 DB 类的方法:
DB::enableQueryLog(); dd(DB::getQueryLog());
使用enableQueryLog()函数打开SQL记录,然后是正常的数据库逻辑,最后,使用 getQueryLog() 方法获取一个包含了生成的SQL语句,还有绑定的参数。
上述语句打印的结果大致如下:
还有一种方法,就是链式调用 QueryBuilder 的 toSql 方法,即可打印当前模型的SQL语句,而并不执行。
DB::table("users")->toSql()
上述方法输出的结果:
select * from `users`
当然只要是返回的 QueryBuilder 对象,均可使用。所以使用where子句查询后,直接打印较为方便。
但是 toSql 获取的只是带参数绑定的SQL,不打印参数。我们可以这样打印完整的语句:
$query = DB::table("users")->where("id", 10);$sql = str_replace_array("?", $query->getBindings(), $query->toSql());dd($sql);
生成的SQL语句,使用问号作为位置参数,如果想要格式化输出,还可以使用 vsprintf 这个函数:
$query = str_replace(array("?"), array(""%s""), $builder->toSql()); $query = vsprintf($query, $builder->getBindings()); dump($query);
效果与 str_replace_array 是一样的。
再进一步
还有一种思路,就是在 illumination 发起查询的时候,使用事件钩子,打印出SQL语句。有没有这样的钩子呢?laravel自然是有的。
Event::listen("illuminate.query", function($query, $params, $time, $conn) { dd(array($query, $params, $time, $conn));});
其中 illuminate.query 就是查询发起的事件钩子。
效果跟上一节所用方法相同,不再演示。
写在最后
本文通过3种方法打印出程序上下文所生成的SQL语句,可以优化查询的时候,起到很好的作用。
Happy coding :-)
我是 @程序员小助手 ,持续分享编程知识,欢迎关注。