Laravel 写入sql日志

1.laravel5.4

在/app/Providers/AppServiceProvider.php代码如下

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use DB;
class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            $sql = str_replace("?", "'%s'", $query->sql);
            $log = vsprintf($sql, $query->bindings);
            $log = '[' . date('Y-m-d H:i:s') . '] ' . $log . "\r\n";
            $filepath = storage_path('logs\sql.log');
            file_put_contents($filepath, $log, FILE_APPEND);
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

最终日志会显示在\storage\logs\sql.log

2.laravel5.*

使用监听器

第一步:创建监听器

php artisan make:listener QueryListener --event=illuminate.query

生成文件于 app/Listeners/QueryListener.php

然后删除 app/Listeners/QueryListener.php 顶部的 use App\Events\illuminate.query;, 这是自动生成的。

第二步:注册事件

打开 app/Providers/EventServiceProvider.php,在 $listen 中添加 illuminate.query 事件的监听器为 QueryListener

protected $listen = [
        'illuminate.query' => [
            QueryListener::class,
        ],
    ];
当然在类前面你需要  use App\Listeners\QueryListener;  不然就报类不存在了。

第三步:添加逻辑

修改上面生成的文件,我们把 SQL 查询记录到日志里,所以编辑 handle 方法为:

    /**
     * Handle the event.
     *
     * @param  Events  $event
     * @return void
     */
    public function handle($sql, $params)
    {
        if (env('APP_ENV', 'production') == 'local') {
            foreach ($params as $index => $param) {
                if ($param instanceof DateTime) {
                    $params[$index] = $param->format('Y-m-d H:i:s');
                }
            }
            $sql = str_replace("?", "'%s'", $sql);
            array_unshift($params, $sql);
            Log::info(call_user_func_array('sprintf', $params));
        }
    }


上面我们用到了两个类:Log 与 DateTime, 别忘记引入它们。

解释一下上面的代码:

  1. illuminate.query 事件触发时的参数为两个:handle($sql, $params), SQL 预处理语句与查询参数值;
  2. 我们只在开发环境记录 SQL:env('APP_ENV', 'production') == 'local'
  3. 我们的参数里可能存在日期类型,所以直接记日志会报错,所以处理一下:$param instanceof DateTime

然后跑一下试试吧,应该在日志里就能看到:

[2017-11-09 05:31:57] local.INFO: select * from `bk_article_position` where `is_delete` = '1' and `is_active` = '1' order by `id` desc  
[2017-11-09 05:31:57] local.INFO: select * from `bk_article_tags` where `is_delete` = '1' and `is_active` = '1' order by `id` desc  
[2017-11-09 05:31:57] local.INFO: select * from `bk_article_position` where `is_delete` = '1' and `is_active` = '1' order by `id` desc  

最终显示在\storage\logs\laravel.log

3.使用以上两个有一些问题我把最新的更新上去

在/app/Providers/AppServiceProvider.php代码如下

    public function boot()
    {

      
        DB::listen(function ($sql) {

            foreach ($sql->bindings as $i => $binding) {
                if ($binding instanceof \DateTime) {
                    $sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
                } else {
                    if (is_string($binding)) {
                        $sql->bindings[$i] = "'$binding'";
                    }
                }
            }
    
            // Insert bindings into query
            $query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);
    
            $query = vsprintf($query, $sql->bindings);
    
            // Save the query to file
            $logFile = fopen(
                storage_path('logs' . DIRECTORY_SEPARATOR . date('Y-m-d') . '_query.log'),
                'a+'
            );
            fwrite($logFile, date('Y-m-d H:i:s') . ': ' . $query . PHP_EOL);
            fclose($logFile);

        });
    }

上面方法均参考网上实例得来,如有侵权,请联系我,删除


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值