[Laravel] 纪录完整 SQL Query 语法
(图片来源)
纪录 SQL Query 的两种方式:
1. $query->tosql();
2. DB::getQueryLog();
1. 第一个方式 tosql()
适用 ORM 的 SQL 语法储存于 $query 变数中这种写法,当然变数名可自行定义。
$query = DB::table('scan'); $query->select('scan.id', 'scan.title', 'scan.scan_cate', 'scan.show_date', 'scan.writer_id', 'scan.counter'); if (!empty($data['keyword'])) { $query->where('scan.title', 'LIKE', '%' . $data['keyword'] . '%'); } $query->orderBy('show_date', 'desc'); $scans = $query->limit(300)->get(); $stringSql = $query->tosql(); echo $stringSql;
这种取出 SQL Query 的方式,结果会是单一字串,如下:
select `scan`.`id`, `scan`.`title`, `scan`.`scan_cate`, `scan`.`show_date`, `scan`.`writer_id`, `scan`.`counter` from `scan` where `scan`.`title` LIKE ? order by `show_date` desc limit 300 |
2. 第二个方式 DB::getQueryLog()
适用取得多个 Query 语法,取出结果会是多维阵列的形式,这种方式比较不同的地方是它除了 Query 字串还包含相关参数与执行时间等资讯,如下。
array(2) { [0]=> array(3) { ["query"]=> string(263) "select `scan`.`id`, `scan`.`title`, `scan`.`scan_cate`, `scan`.`show_date`, `scan`.`writer_id`, `scan`.`counter` from `scan` where `scan`.`title` LIKE ? and `scan`.`show_date` between ? and ? order by `show_date` desc limit 300" ["bindings"]=> array(3) { [0]=> string(6) "%test%" [1]=> string(10) "2017-09-10" [2]=> string(10) "2017-09-13" } ["time"]=> float(73.97) } [1]=> array(3) { ["query"]=> string(263) "select `scan`.`id`, `scan`.`title`, `scan`.`scan_cate`, `scan`.`show_date`, `scan`.`writer_id`, `scan`.`counter` from `scan` where `scan`.`title` LIKE ? and `scan`.`show_date` between ? and ? order by `show_date` desc limit 300" ["bindings"]=> array(3) { [0]=> string(6) "%test%" [1]=> string(10) "2017-09-10" [2]=> string(10) "2017-09-13" } ["time"]=> float(20.73) } }
但这两种方式有共同的缺点,就是 Query 字串都不是可以直接拿来执行的 SQL 语法,相信眼尖的各位有发现 Query 字串中都有 ? 字元的存在,这是因为 Laravel 本身 ORM 的处理方式所造成的,那要如何产出可以原始且可以执行的 Query 语法呢?
我这边有实作一个 function 来做 ? 字元的取代处理,相关程式码如下:
/** * 取得当前的 query string * @return string * @date 2017-09-08T10:32:43+0800 */ public static function getQueryString() { $queryLog = DB::getQueryLog(); $lastQuery = end($queryLog); $stringSql = $lastQuery['query']; // 取代所有问号 $stringSql = preg_replace("/\?/", "'?'", $stringSql); // query 重组 foreach( $lastQuery['bindings'] as $arg ) { $stringSql = preg_replace("/\?/", $arg, $stringSql, 1); } return $stringSql; }
参考:
Get the last query executed in Laravel
Debugging Queries in Laravel