Laravel 4 – loggingSQL查询

关于在Laravel 4中loggingSQL查询,已经有几个问题了。但是我已经尝试了几乎所有的问题,但仍然没有按照我想要的方式工作。

这是我的情况

  1. 在我的php视图文件中,我向服务器发出AJAX请求
  2. 收到AJAX请求并运行RAW参数化Postgres SQL查询(例如,

    DB :: select('select * from my_table where id =?',array(1))

如果我使用

Event::listen('illuminate.query', function($sql) { Log::error($sql); }); 

我刚刚得到“select * from my_table where id =?” 作为没有实际填充ID值的日志消息。

如果我使用

 $queries = DB::getQueryLog(); $last_query = end($queries); Log::error(print_r($last_query, true)); 

我仍然没有填充ID的最终SQL查询。

最后,如果我使用像https://github.com/loic-sharma/profiler这样的日志logging工具,它不会显示任何内容,因为我正在发出一个AJAX请求。

我用尽了我的select吗? 还有更好的办法吗?

这是我目前使用的SQL查询logging。 你应该可以把这个放到你的主路由文件中,然后在你的数据库configuration里添加'log'=> true。

 if (Config::get('database.log', false)) { Event::listen('illuminate.query', function($query, $bindings, $time, $name) { $data = compact('bindings', 'time', 'name'); // Format binding data for sql insertion foreach ($bindings as $i => $binding) { if ($binding instanceof \DateTime) { $bindings[$i] = $binding->format('\'Ymd H:i:s\''); } else if (is_string($binding)) { $bindings[$i] = "'$binding'"; } } // Insert bindings into query $query = str_replace(array('%', '?'), array('%%', '%s'), $query); $query = vsprintf($query, $bindings); Log::info($query, $data); }); } 

感谢Jeemusu回答有关将绑定插入到准备好的语句中的一些信息。

您应该能够通过传递$bindings作为Event函数的第二个参数来查找绑定。

 Event::listen('illuminate.query', function($sql, $bindings, $time){ echo $sql; // select * from my_table where id=? print_r($bindings); // Array ( [0] => 4 ) echo $time; // 0.58 // To get the full sql query with bindings inserted $sql = str_replace(array('%', '?'), array('%%', '%s'), $sql); $full_sql = vsprintf($sql, $bindings); }); 

在Laravel 3.x中,我认为事件监听器被称为laravel.query

继续@Collin詹姆斯答案 。

如果你想login到一个单独的文件只有SQL,你可以这样做:

 if (Config::get('database.log', false)) { Event::listen('illuminate.query', function($query, $bindings, $time, $name) { $data = compact('bindings', 'time', 'name'); // Format binding data for sql insertion foreach ($bindings as $i => $binding) { if ($binding instanceof \DateTime) { $bindings[$i] = $binding->format('\'Ymd H:i:s\''); } else if (is_string($binding)) { $bindings[$i] = "'$binding'"; } } // Insert bindings into query $query = str_replace(array('%', '?'), array('%%', '%s'), $query); $query = vsprintf($query, $bindings); $log = new Logger('sql'); $log->pushHandler(new StreamHandler(storage_path().'/logs/sql-' . date('Ym-d') . '.log', Logger::INFO)); // add records to the log $log->addInfo($query, $data); }); } 

有了这个在你的文件的顶部:

 use Monolog\Logger; use Monolog\Handler\StreamHandler; 

这会将所有查询logging到storage/logs/一个名为sql-YYYY-mm-dd.log中。

尽pipe接受的答案是正确的,但是这个答案解释了如何在使用jQuery进行Ajax请求时更新loic-sharma分析器 。 使用这种方法不需要读取文件日志。

步骤1

第一个问题是在每个Ajax请求中发送更新的探查器数据给客户端。 这可以使用Laravel应用程序的“after”事件来解决。

应用程序/ filters.php:

 App::after(function($request, $response) { // If it's a JsonResponse and the profiler is enabled, include it in the response. if($response instanceof \Illuminate\Http\JsonResponse && Profiler::isEnabled()) { $profiler = Profiler::getFacadeRoot(); $profilerJson = json_encode($profiler->render()); $content = substr($response->getContent(), 0, -1) . ',"profiler":' . $profilerJson . '}'; $response->setContent($content); } }); 

App::afterfilter将在每个Laravel请求上运行。 上面的闭包的第一行确保只有当响应是JsonResponsetypes并且启用了分析器时才会继续。 如果是这种情况,则渲染剖析器并将HTML附加到JSON对象。

注意:这段代码假定返回的JSON是一个对象。 所以它会失败的数组: Response::json(array(1,2,3))

第2步

现在,更新的分析器HTML正在发送到客户端,我们必须使用JavaScript更新新的分析器HTML的DOM。 每当客户端获得JSON响应时,都会发生这种情况。 jQuery提供了全局的Ajax事件处理程序,这对于实现这一点来说是完美的。

 $(document).ajaxSuccess(function(event, request, settings) { try { json = jQuery.parseJSON(request.responseText); if(json.profiler) { renderProfiler(json.profiler); } } catch(error) { // Its not JSON. return; } }); 

这是一个用新的replace旧的分析器的方法:

 renderProfiler = function(data) { // Remove previous $anbu = $('.anbu'); $anbu.prev().remove(); // Removes <style> tag of profiler $anbu.next().next().remove(); // Removes the inline script tag of profiler $anbu.next().remove(); // Removes jQuery script tag by the profiler $anbu.remove(); // Removes the <div> tag of profiler $(document.body).append(data); }; 

使用它

现在就像返回响应一样简单:

 return Response::json(array( 'user' => Auth::user() )); 

Laravel将追加分析器HTML。 JavaScript将捕获JSON响应并更新DOM。 您将在网页上拥有SQL查询和计时。

注意

在testing代​​码时,可能会有一两个错误。 这也不完全是我如何做到的。 我没有在json响应中发送HTML,而是使用探查器的实际数据扩展对象。 在客户端,我使用小胡子模板呈现分析器。

虽然这个问题最初是针对Laravel 4的,但是我仍然通过google来到这里,但是我正在使用Laravel 5。

有一些新的方法可以使用中间件loggingLaravel 5中的所有查询 ,但是如果您更喜欢相同的方法,那么Collin James提供的代码相同,但是Laravel 5

 if (Config::get('database.log', false)) { Event::listen('Illuminate\Database\Events\QueryExecuted', function($query) { $bindings = $query->bindings; $time = $query->time; $name = $query->connection->getName(); $data = compact('bindings', 'time', 'name'); // Format binding data for sql insertion foreach ($bindings as $i => $binding) { if ($binding instanceof \DateTime) { $bindings[$i] = $binding->format('\'Ymd H:i:s\''); } else if (is_string($binding)) { $bindings[$i] = "'$binding'"; } } // Insert bindings into query $query = str_replace(array('%', '?'), array('%%', '%s'), $query->sql); $query = vsprintf($query, $bindings); Log::info($query, $data); }); } 

这就是我一直在使用的:

 DB::listen(function ($query, $bindings, $time, $connection) { $fullQuery = vsprintf(str_replace(array('%', '?'), array('%%', '%s'), $query), $bindings); $result = $connection . ' (' . $time . '): ' . $fullQuery; dump($result); // You can of course log the $result });