---
## 一、 toSql() 方法把問號打印成具體的值
```php
$sql = Student::query()->where('id', $id)->toSql();
$studentSemesters = Student::query()->where('id', $id)->getBindings(); //得到綁定的數組
$sql = str_replace('?', '%s', $sql); //替換問號字符
$sql = sprintf($sql, ...$studentSemesters); //返回一個根據格式化字符串 sql 生成的字符串。
dd($sql);
```
## 二、 利用監聽事件的方式打印 SQL 語句到日志中
> 配置 `EventServiceProvider.php` 的, 第一種方式直接寫在 boot 方法中
```php
/**
* 記錄日志, 格式化輸出sql
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
DB::listen(function (QueryExecuted $event){
$sql = $event->sql;
$bindings = $event->bindings;
$time = $event->time;
$bindings = array_map(function ($bindings){
if(is_string($bindings)){
return "'$bindings'";
}else if($bindings instanceof \DateTime){
return $bindings->format("'Y-m-d H:i:s'");
}
return $bindings;
}, $bindings);
$sql = str_replace('?','%s',$sql);
$sql = sprintf($sql, ...$bindings);
Log::info('sql log',['sql' => $sql, 'time' => $time]);
});
}
```
> #### 第二種方式:生成數據庫的監聽器
php artisan make:listener DBSqlListener
---
> 配置 `EventServiceProvider` 中的
protected $listen = [
QueryExecuted::class => [
DBSqlListener::class,
]
];
//保持不變
public function boot()
{
parent::boot();
}
> #### 在新生成的監聽文件中配置如下:
class DBSqlListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle(QueryExecuted $event)
{
//日志只允許在測試和本地環境輸出
if(!app()->environment(['testing', 'local'])){
return;
}
$sql = $event->sql;
$bindings = $event->bindings;
$time = $event->time;
$bindings = array_map(function ($bindings){
if(is_string($bindings)){
return "'$bindings'";
}else if($bindings instanceof \DateTime){
return $bindings->format("'Y-m-d H:i:s'");
}
return $bindings;
}, $bindings);
$sql = str_replace('?','%s',$sql);
$sql = sprintf($sql, ...$bindings);
Log::info('sql log2',['sql' => $sql, 'time' => $time]);
}
}
#### 最后我們查看其日志輸出情況
