37150038940_1520f95a76_z.jpg

(图片来源)

纪录 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 

相关文章