---
## 一、 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]);
}
}
#### 最后我们查看其日志输出情况
![图片alt](/media/editor/1630325148148_20210830200554710966.png ''图片title'')