Уже есть несколько вопросов относительно регистрации SQL-запроса в Laravel 4. Но я пробовал почти все из них, и он все еще не работает так, как я хочу.
Вот моя ситуация
Запрос AJAX принимается и запускает параметризованный RAW-запрос Postgres SQL (например,
DB :: select ('select * from my_table где id =?', Array (1))
Если я использую
Event::listen('illuminate.query', function($sql) { Log::error($sql); });
Я просто получаю «select * from my_table, где id =?» как сообщение журнала без фактического заполнения идентификатора.
Если я использую
$queries = DB::getQueryLog(); $last_query = end($queries); Log::error(print_r($last_query, true));
У меня до сих пор нет окончательного SQL-запроса с заполненным идентификатором.
Наконец, если я использую инструмент ведения журнала, например https://github.com/loic-sharma/profiler, он ничего не отображает, так как я делаю запрос AJAX.
Я исчерпал свои возможности? Есть ли еще лучший способ?
Вот что я сейчас использую для регистрации sql-запросов. Вы должны убрать это в свой основной файл маршрутов, а затем добавить «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 Джеймс ответить .
Если вы хотите войти в отдельный файл только для 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;
Это будет записывать все ваши запросы в файл с именем sql-YYYY-mm-dd.log
в storage/logs/
.
Хотя принятый ответ правилен, в этом ответе объясняется, как обновлять профилировщик loic-sharma при выполнении запросов Ajax с использованием jQuery. Используя этот подход, не нужно читать журналы файлов.
Первая проблема заключается в отправке обновленных данных профилировщика клиенту по каждому запросу Ajax. Это можно решить, используя «после» события приложения Laravel.
Приложение / 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::after
будет запускаться при каждом запросе Laravel. Первая строка закрытия выше, гарантирует, что она будет продолжаться только в том случае, если ответ имеет тип JsonResponse и включен профайлер. Если это так, отрисуйте профилировщик и добавьте HTML в объект JSON.
Примечание: этот код предполагает, что возвращаемый JSON является объектом. Поэтому он не будет работать для массивов: Response::json(array(1,2,3))
.
Теперь, когда обновленный HTML-код профилировщика отправляется клиенту, мы должны обновить DOM с помощью нового HTML-кода профилировщика, используя javascript. Это должно происходить каждый раз, когда клиент получает ответ 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; } });
Ниже приведен метод замены старого профайлера на новый:
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-запросы и тайминги прямо на веб-странице.
Пока код проверен, может быть ошибка или два. Это также не совсем так, как я это делаю. Вместо отправки HTML в json-ответе я распространяю объект с фактическими данными из профилировщика. На стороне клиента я обрабатываю профилировщик с использованием шаблона уса .
Хотя вопрос был первоначально нацелен на Laravel 4, я все же оказался здесь через google, но я использую Laravel 5.
Есть новые способы для регистрации всех запросов в Laravel 5 с использованием Middleware , но если вы предпочитаете тот же подход, здесь тот же код, предоставленный 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 });