Pull to refresh

Узнать и полюбить Xdebug

Reading time6 min
Views76K
Original author: Bruno Skvorc
Вот уже 15 лет прошло со времен первого релиза Xdebug. Прекрасный повод вновь представить эту систему миру и объяснить как и почему она делает то что делает.
image
Xdebug — это расширение для PHP (должно быть скомпилировано и установлено в процессе установки PHP) которое представляет разработчику следующий функционал для отладки:

  • Трассировки стека — вывод подробного пути, который привел приложение к полученной ошибке, включая параметры переданные в функции, в порядке позволяющем легко отследить ошибку
  • Более приятный вывод var_dump, создающий подсветку кода и структурированный вид вместе с дампом суперглобальных переменных, по аналогии с VarDumper.
  • Профайлер для поиска узких мест кода с возможностью визуализированного представления графиков производительности внешними инструментами. В результате получается график похожий на графики из Blackfire.
  • Удаленный отладчик, который может быть использован при соединении с Xdebug для запуска и выполнения кода в IDE или браузере построчно через брейк-пойнты.
  • “Покрытие кода” которое показывает какая часть кода была выполнена в процессе запроса. Это функция нужна по большей части для юнит-тестов и получения информации о том насколько хорошо ваш код покрыт тестами.

Как мне использовать его?


Xdebug поставляется с подробной инструкцией по установке в которой учтены практически все возможные варианты использования, хотя, если вы хотите поэкспериментировать с представленным ниже функционалом, мы рекомендуем использовать Homestead Improved так как там Xdebug установлен и активирован по умолчанию.

Зачем вообще нужен Xdebug когда есть современные IDE и Blackfire?


Современные IDE предоставляют широкие возможности поиска по коду, так что полезность функционала форматирования ссылок кажется сомнительной. Существуют всевозможные системы логирования способные обрабатывать ошибки и исключения. Также, трассировка и профилирование функций прекрасно реализованы в Blackfire. Не смотря на все это, форматирование ссылок на файлы лишь одна из функций Xdebug, а использование Blackfire связано с собственными трудностями — установка расширения, настройка горячих клавиш, и оплата сохранения истории трассировок. А использование логгеров требует внимательности, так как добавить их в приложение на поздних этапах не самая простая задача.

Но область использования Xdebug не ограничивается лишь этим. Он всё ещё необходим для правильного модульного тестирования (тестируемые фреймворки зависимы от его отчетов о покрытии кода), далеко не так легко провести отладку через удаленные брейк-пойнты другими средствами, а этот инструмент настолько старый и стабильный, что был отшлифован почти до идеала.

Конечно, нет никакой необходимости использовать Xdebug, если ваш текущий инструментарий может обеспечить всё что он предоставляет, или если вам не нужны его возможности, однако у меня не было еще ни одного проекта который можно было бы завершить так же эффективно без его использования.

Давайте попробуем


Предполагается что на этом этапе у вас уже есть среда с работающим Xdebug. Если нет, попробуйте воспользоваться Homestead Improved.

Давайте создадим новый проект состоящий из одного файла index.php и выведем несуществующую переменную $foo:

<?php

echo $foo;

Вот что мы получим:

image

Отключение Xdebug


Блоки уведомлений подобные этому настолько привычное явление в наше время, что большинство людей даже не понимает что они уже стилизованы с помощью Xdebug. Чтобы доказать это давайте посмотрим как бы это сообщение выглядело без Xdebug. Для отключения Xdebug отредактируем файл /etc/php/7.1/fpm/conf.d/20-xdebug.ini в Homestead Improved, и закомментируем первую строку:

;zend_extension=xdebug.so
xdebug.remote_enable = 1
xdebug.remote_connect_back = 1
xdebug.remote_port = 9000
xdebug.max_nesting_level = 512

После чего нужно перезапустить PHP-FRM:

sudo service php7.1-fpm restart

Примечание: если вы используете среду разработки с другой версией PHP, файл настроек вашего Xdebug скорее всего будет в другом месте. Сверьтесь с документацией системы чтобы найти его или задайте вопрос в комментариях.

image

Выглядит довольно скудно, не так ли? Из вывода пропал весь стек вызовов. Конечно, пока эта информация не слишком полезна, так как мы работаем только с одной строкой в единственном файле, но позже мы будем использовать ее довольно часто.

Теперь вновь активируем Xdebug, раскомментировав строку в отредактированном ранее файле, и продолжим. Не забудьте перезапустить PHP!

Переходы по файлам


Если у вас есть любимая IDE (у меня, например, PhpStorm), возможность переходить к файлам в ней простым кликом в трассировке стека была бы определенно полезной и значительно увеличила бы скорость отладки. Я продемонстрирую как реализовать эту возможность для PhpStorm.

Давайте снова откроем файл 20-xdebug.ini и добавим в него следующее:

xdebug.file_link_format = phpstorm://open?%f:%l

Заметьте, что не во всех браузерах это будет работать. Например, у Opera возникнут проблемы со ссылкой phpstorm:// и она радостно упадет, в то время как Firefox и Chrome прекрасно обрабатывают такие ссылки.

Если теперь обновить нашу PHP страницу с ошибкой, мы получим ссылки открывающие IDE сразу в точном местоположении ошибки:

image

Настройка для работы с другими IDE и редакторами происходит точно так же.

Xdebug, Vagrant и PhpStorm


Зачем останавливаться на этом? Многие сегодня используют для разработки виртуальные машины, позволяющие быть уверенным в том что никакая часть из среды исполнения PHP не затронет основную машину, при этом сохраняя всё быстрым и гладким. Как ведет себя Xdebug в таких случаях? Кроме того, возможно ли, в принципе, выполнять отладку с брейк-поинтами, когда вы проходите по своему коду и проверяете каждую строку отдельно?

К счастью, Xdebug отлично поддерживает использование брейк-пойнтов при удаленном соединении. Мы рассмотрели этот процесс выше, а полностью иллюстрированное руководство по настройке вы можете найти в этой статье.

Использование профайлера.


В конце давайте рассмотрим одну из часто игнорируемых функций: профайлер. Для этого нам понадобится какое-нибудь крупное приложение, например Laravel:

composer create-project --prefer-dist laravel/laravel xdebug

И снова нам нужно внести правки в файл 20-xdebug.ini, добавив следующее:

xdebug.profiler_enable_trigger = 1
xdebug.profiler_output_dir = /home/vagrant/Code/

Заметьте — мы не используем xdebug.profiler_enable = 1, так как не хотим чтобы он оставался включенным всё время. Вместо этого мы используем триггерный параметр в запросе “XDEBUG_PROFILE” для выборочной активации. Также мы выводим профиль кэша в основную общую папку нашей виртуальной машины, получая возможность работать с ним в операционной системе хоста.

После перезапуска PHP мы можем проверить это выполнив homestead.app/?XDEBUG_PROFILE (замените homestead.app на имя выбранного вами виртуального хоста или IP-адрес виртуальной машины). Конечно же, файл там где и ожидалось:

image

В каждой операционной системе есть собственный инспектор кэширования, для OS X, например, можно использовать qcachegring, который легко устанавливается через Homebrew. После установки…

brew install qcachegrind --with-graphviz

… и открытия файла, мы видим удобное разбиение потока выполнения:

image

Профайлер предоставляет детализированный доступ ко многим данным и возможность досконально изучить поведение вашего кода, также как и в Blackfire. Однако с локальным выводом профайлера намного легче автоматизировать непрерывное отслеживание производительности и сложности выполнения.

Принудительное отображение Xdebug в Laravel


По умолчанию, Laravel имеет собственные отчеты об ошибках и настройки рендеринга. Ошибка, вроде той что мы вызвали ранее с неопределенной переменной, в Laravel будет выглядеть так:

<?php

use Illuminate\Http\Request;

Route::get('/', function(Request $request){
    echo $foo;
    return view('welcome');
});

image

Хотя экран ошибок Symfony (который Laravel использует в этом случае) способен так же хорошо работать с переходами Xdebug (попробуйте! Вы можете кликнуть по этим файлам и их строкам!), мне очень не хватает вывода информации о памяти (Xdebug по умолчанию выводит отчет об использовании памяти в каждый момент времени в трассировке). Давайте вернемся к экрану Xdebug в режиме разработки, чтобы отследить этот параметр.

<?php
use Illuminate\Http\Request;

Route::get('/', function(Request $request){
    ini_set('display_errors', 1);
    restore_error_handler();
    echo $foo;
    return view('welcome');
});

Как видите мы обновили наш роутинг по умолчанию таким образом, чтобы сначала он активировал отображение ошибок (экран который мы видели ранее не показывает ошибки сразу при появлении, а сохраняет в стек исключений который был позже извлечен и визуализирован), затем мы возвращаем обработчик ошибок в его значение по умолчанию переопределяя значение Laravel.

После обновления, конечно же, вернулся наш старый экран — просто взгляните на эту простыню трассировки стэка и потребления памяти.

image

Я советую вам продолжить дальнейшее изучение самостоятельно — просмотрите документацию, поиграйте с настройками, выясните сколько всего вы можете узнать о ваших приложениях.

Заключение


Xdebug — ценный инструмент в наборе любого разработчика. Это мощное расширение полностью соответствует своему названию, делая язык, с которым мы ежедневно работаем, более подробным, дружелюбным и менее загадочным при возникновении ошибок.

За 15 лет своего существования Xdebug установил высокие стандарты для отладочных средств. Я хотел бы поблагодарить Дерика за разработку и поддержку всё это время, и буду рад если вы решите написать одно-два руководства об углубленном использовании, подводных камнях или скрытых комбинациях функций о которых никто не задумывался прежде. Давайте поможем его распространению и развитию и в следующие 15 лет.

С днём рождения, Xdebug!
Tags:
Hubs:
Total votes 18: ↑17 and ↓1+16
Comments20

Articles