В процессе разработки на Drupal иногда возникает необходимость проанализировать, какие SQL-запросы выполняются при обработке того или иного запроса. Стандартный интерфейс Devel (например, панель внизу страницы) отлично справляется с этой задачей для обычных HTML-страниц.
Однако, что делать, если мы имеем дело с AJAX-запросом, загрузкой файла через file_transfer() или другими нестандартными точками входа, где стандартный вывод недоступен? В этой статье мы рассмотрим программный способ получения лога запросов с помощью API модуля Devel, который работает в любом контексте.
Модуль Devel предоставляет удобный механизм логирования запросов. Чтобы получить список всех выполненных SQL-запросов за текущий запрос, достаточно использовать следующий код:
|
1 |
$queries = (devel_query_enabled() ? Database::getLog('devel', 'default') : NULL); |
Здесь:
devel_query_enabled()– проверяет, включено ли логирование запросов в настройках Devel.Database::getLog('devel', 'default')– возвращает объект-логгер для каналаdevelи целевой базы данныхdefault(обычно это основная БД). Этот объект содержит массив выполненных запросов, время выполнения, стек вызовов и другую полезную информацию.
Важно: данный метод работает только при условии, что модуль Devel установлен и в его настройках включена опция «Collect query log» (находится в разделе /admin/config/development/devel).
Зачем это нужно?
В типичной разработке мы видим отладочную панель Devel на каждой странице. Но при запросах, которые не возвращают HTML-ответ (AJAX, file_transfer, кроны, миграции и т.д.), панель не рендерится, и мы лишены возможности оценить производительность или найти проблемные запросы. Программное получение лога позволяет:
- Вставить код в любую точку выполнения (например, прямо перед завершением скрипта);
- Вывести данные в лог-файл, в переменную сессии или даже отправить в мессенджер для оперативного анализа;
- Использовать в интерактивной отладке с Xdebug, ставя точки останова в нужных местах.
Практический пример: отладка загрузки файла
Рассмотрим ситуацию, когда необходимо проанализировать все запросы, выполненные во время обработки запроса на скачивание файла. В Drupal 7 за выдачу файлов отвечает функция file_transfer() (находится в includes/file.inc). Запрос завершается вызовом drupal_exit() после отправки файла, и никакого HTML-вывода не происходит.
Как нам перехватить лог запросов? Очень просто:
- Убедитесь, что у вас включено логирование Devel.
- Откройте файл
includes/file.inc(или соответствующий контроллер в современном Drupal) и поставьте точку останова на строке сdrupal_exit()(или в деструкторе, который вызывается после завершения скрипта, но проще всего воспользоваться точкой останова в IDE). - В момент остановки выполните в окне отладки (или добавьте временный код) следующий фрагмент:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if (devel_query_enabled()) { $log = Database::getLog('devel', 'default'); // Теперь мы можем распечатать запросы в удобном виде. foreach ($log as $query_info) { $query = $query_info['query']; $args = $query_info['args'] ?? []; // Можно вывести в лог, в файл, в переменную сессии. // Или в отладчике посмотреть локальные переменные. error_log(strtr($query, $args)); // Там много полезных данных, // в том числе - продолжительность запроса: $duration = $query_info['time']; ... } } |
После этого в логах PHP (или в консоли сервера) появятся все выполненные SQL-запросы с подставленными параметрами. Это позволит увидеть, какие запросы инициируются при скачивании файла, и оптимизировать их при необходимости.
