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;
Вот что мы получим:
Отключение 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 скорее всего будет в другом месте. Сверьтесь с документацией системы чтобы найти его или задайте вопрос в комментариях.
Выглядит довольно скудно, не так ли? Из вывода пропал весь стек вызовов. Конечно, пока эта информация не слишком полезна, так как мы работаем только с одной строкой в единственном файле, но позже мы будем использовать ее довольно часто.
Теперь вновь активируем Xdebug, раскомментировав строку в отредактированном ранее файле, и продолжим. Не забудьте перезапустить PHP!
Переходы по файлам
Если у вас есть любимая IDE (у меня, например, PhpStorm), возможность переходить к файлам в ней простым кликом в трассировке стека была бы определенно полезной и значительно увеличила бы скорость отладки. Я продемонстрирую как реализовать эту возможность для PhpStorm.
Давайте снова откроем файл 20-xdebug.ini и добавим в него следующее:
xdebug.file_link_format = phpstorm://open?%f:%l
Заметьте, что не во всех браузерах это будет работать. Например, у Opera возникнут проблемы со ссылкой phpstorm:// и она радостно упадет, в то время как Firefox и Chrome прекрасно обрабатывают такие ссылки.
Если теперь обновить нашу PHP страницу с ошибкой, мы получим ссылки открывающие IDE сразу в точном местоположении ошибки:
Настройка для работы с другими 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-адрес виртуальной машины). Конечно же, файл там где и ожидалось:
В каждой операционной системе есть собственный инспектор кэширования, для OS X, например, можно использовать qcachegring, который легко устанавливается через Homebrew. После установки…
brew install qcachegrind --with-graphviz
… и открытия файла, мы видим удобное разбиение потока выполнения:
Профайлер предоставляет детализированный доступ ко многим данным и возможность досконально изучить поведение вашего кода, также как и в Blackfire. Однако с локальным выводом профайлера намного легче автоматизировать непрерывное отслеживание производительности и сложности выполнения.
Принудительное отображение Xdebug в Laravel
По умолчанию, Laravel имеет собственные отчеты об ошибках и настройки рендеринга. Ошибка, вроде той что мы вызвали ранее с неопределенной переменной, в Laravel будет выглядеть так:
<?php
use Illuminate\Http\Request;
Route::get('/', function(Request $request){
echo $foo;
return view('welcome');
});
Хотя экран ошибок 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.
После обновления, конечно же, вернулся наш старый экран — просто взгляните на эту простыню трассировки стэка и потребления памяти.
Я советую вам продолжить дальнейшее изучение самостоятельно — просмотрите документацию, поиграйте с настройками, выясните сколько всего вы можете узнать о ваших приложениях.
Заключение
Xdebug — ценный инструмент в наборе любого разработчика. Это мощное расширение полностью соответствует своему названию, делая язык, с которым мы ежедневно работаем, более подробным, дружелюбным и менее загадочным при возникновении ошибок.
За 15 лет своего существования Xdebug установил высокие стандарты для отладочных средств. Я хотел бы поблагодарить Дерика за разработку и поддержку всё это время, и буду рад если вы решите написать одно-два руководства об углубленном использовании, подводных камнях или скрытых комбинациях функций о которых никто не задумывался прежде. Давайте поможем его распространению и развитию и в следующие 15 лет.
С днём рождения, Xdebug!
Комментарии (20)
olku
05.05.2017 20:38+1И тормозит мощно, в разы и до порядка, в зависимости от сложности трассируемой системы. Идеальней некуда :) Есть ли альтернативы?
xRay
05.05.2017 21:17+1Не надо его постоянно включенным держать. И надо настроить его что бы профилирование и трассировка включались только по триггерам. Не держать Xdebug на продакшен сервере постоянно включенным.
Для профилирования есть Xhprof. Для мониторинга Pinba.
Artiomtb
05.05.2017 23:51В «отключении xdebug» и «переходах по фалам» одна и та же картинка загружена, исправьте
vtvz_ru
06.05.2017 00:53Люблю его. Особенно спасает, когда нужно проверить математику в проекте, как цифры меняются. Всяко проще, чем смотреть вывод обычного var_dump или echo
benbor
06.05.2017 11:16А с версии xdebug 2.4.0rc2 ребята взяли, и отключили возможность показывать адреса переменных в памяти :( И ничего не предложили в замен… Приходится пользоваться старым xdebug.
ps для тех, кто не понимает о чем я: картинкаvtvz_ru
06.05.2017 21:20+2А какова практическая польза для этого? (не критика, просто личный интерес)
benbor
10.05.2017 17:19Полезно при дебаге. Например если в
макаронномсложном коде, из цикла в цикл состояние объекта неадекватно меняется, иногда, бывает полезно включить данную функцию, и увидеть, что объект то уже не тот (если поменялся адрес, значит кто-то пересоздал или подменил объект).
С ходу лучше примера не придумаю, но, к сожалению, в легаси коде без этого параметра оч трудно
michael_vostrikov
06.05.2017 20:04Для включения XDebug при запросе надо передать GET-параметр XDEBUG_SESSION_START=session_name. session_name это любая строка.
Для включения XDebug в консоли надо перед запуском скрипта выполнить команду
export XDEBUG_CONFIG="idekey=session_name"
для Windows
set XDEBUG_CONFIG="idekey=session_name"
Для возможности подключения XDebug достаточно слушать порт 9000, остальное заморочки IDE.
XDebug добавляет некоторый оверхед. Поэтому если идет много ajax-запросов, они могут накапливаться, пока не обработается каждый. Когда окно мигает при подключении, это хорошо заметно, когда не мигает, кажется что все тормозит. На самом деле это просто прошлые запросы обрабатываются. Могут быть не ajax-запросы, а запросы отсутствующих картинок, которые перенаправляются на index.php, который выдает 404. Помогает отключить ненадолго прослушивание порта.
ghost404
12.05.2017 14:28Уже несколько лет пользуюсь вот этой либой для отладки кода. Удобный аналог var_dump. Гараздо более читаемый и юзабельный. Рендер под web и в cli. Удобное отображение ошибок. Удобней чем в xdebug.
bor1
15.05.2017 07:44аналог var_dump -совершенно верно, но не более.
Гараздо более читаемый и юзабельный. — по сравнению с var_dump.
В xdebug тот же самый вывод можно посмотреть на любом этапе выполнения в IDE + «Evaluate Expression» очень полезный инструмент.ghost404
15.05.2017 14:03Ох, если бы тот же самый.
- Выводятся только данные из доступных переменных.
- Никакой информации о классе (родители, интерфейсы, трейты).
- Никакой информации о интерфейсе класса (методы публичные и приватные).
- Никакой информации о доступе к свойствам класса. Свойства есть, но не известно публичные они или приватные и если приватные, то как их получить.
- Особенно эта проблема ощущается когда проваливаешься по иерархии на 2, 3, 4 и тд уровни.
- Один из главных минусов xdebug — медленный и забивает диск логами профыйлинга, если явно не указать писать лог в один файл. Что не скажешь о либе которую я привел.
- Настраивать профайлинг для Web и CLI сложнее чем для либы которую я упомянул (одна строчка в конфиге и все).
Не скажу что xdebug плох. Просто мне лично он на подходит. Хотя бы потому что медленный.
PS: Я не пиарюсь. Это не моя либа.
dyadyavasya
12.05.2017 20:09Странно, что не упомянули самое главное из-за чего используют Xdebug — возможность расстановки break point в IDE. Лично я без этого как без рук.
Horik_off
Идеальное средство для отладки, но настройка и интеграция с IDE…
В PHPStorm от версии к версии IDE меняется мануал по установке стабильно. Ты думаешь, вроде же так ставил и работало, сейчас то что изменилось, почему параметр а надо теперь выставлять, а раньше без него работало. Вот хотелось бы понимания внутренней кухни этих отладлочных интрументов. Куча мануалов (в том числе и на хабре), а конфижить его все равно сложно как-то.
xRay
Xdebug настраивается в конфиге PHP и ничего в этом плане не менялось уже кучу лет
sayber
Использую PHPStorm уже лет 7-8, и настройки всегда одинаковые (за редким исключением портов и маппинга).
Вы просто настраиваете web application + server и все. Остальное в конфиге PHP.