X

PHP конфигурация XDEBUG

Последнее время работаю в поддержке Magento проектов. Magento имеет совсем не простую кодовую базу, а если добавить модификации предыдущих разработчиков, поиск ошибок становиться невероятно сложным. На помощь приходит XDebug, о нем и пойдет речь..

Какие бывают способы отладки

Начнем с того, что разберемся с тем какие вообще бывают способы отладки.

  • Наиболее простой способ, это вывод состояния переменных в определенном месте программы. Делается это обычно примерно так
    <?php
    $arr = ['a', 'b', 'c'];
    foreach($arr as $k=>$v) {
        if ($v=='b') {
            echo $k.'='.$v; // узнаем какой ключ у элемента со значением 'b'
            exit;
        }
    }
    

    как видите, где-то в программе задаем условия которые нас интересуют и затем выводим данные и прерываем выполнение. Наиболее популярные функции для вывода данных это echo, die, print_r и var_dump.

  • Следующий способ, это опять же вывод состояния переменных, но уже не на экран, а в файл. Все тоже самое, что и в предыдущем варианте, только не выводим на экран, а пишем в файл или базу данных. Зачастую, этот способ называют "логгирование" или "журналирование".
    <?php
    $arr = ['a', 'b', 'c'];
    foreach($arr as $k=>$v) {
        if ($v=='b') {
            file_put_contents('logger.log',$k.'='.$v.PHP_EOL); // узнаем какой ключ у элемента со значением 'b'
        }
    }
    

    Это используется  в тех случаях когда данных много или нужно отслеживать состояние там где нельзя выводить данные на экран, например, на сайте где есть посетители.

  • Следующий способ отладки, это использование отладчиков. Отладчик, это "программа" которая внедряется в интерпретатор кода и позволяет следить за шагами выполнения вашей программы. В большинстве случаев позволяет наблюдать и модифицировать значения переменных во время шагов (сессии отладки). Так же позволяет установить точки останова, позволяющий остановить программу в определенном месте и продолжить её выполнение пошагово или до следующей точки останова. Наиболее известные отладчики это XDebug, PHPDBG и Zend Debugger. Последние два не пользуются популярностью и в данной статье не рассматриваются. Рассматривать будем XDebug.

Пример отладки

Как работает Xdebug

Теперь разберемся как работает XDebug. Начнем вот с такой классической картинки

Схема работы Xdebug

Эта схема, не совсем понятна при первом взгляде на нее, но сейчас мы это исправим.

  1. После того, как вы ввели URL в браузере, на ваш веб-сервер отправляется запрос, по-умолчанию на порт 80. На схеме, это стрелка "HTTP Request".
  2. Далее веб-сервер, обрабатывает запрос и запускает PHP который загружает свои библиотеки, в том числе и XDebug. На схеме, это правый прямоугольник с названием "PHP/Xdebug".
  3. Далее Xdebug проверяет установлена ли опция xdebug.remote_enable (конфигурация описана в след. разделе). Если она установлена в true, то Xdebug понимает, что удаленная отладка доступна, для использования. Итак, у нас она установлена в true, значит XDebug может продолжать работу.
  4. Далее XDebug проверяет, необходимо ли ему запускаться. Для этого он проверяет установлен ли параметр xdebug.remote_autostart в true. Если установлен, то он понимает, что нужно продолжать.  Называется этот вариант - автоматический запуск отладки.
    Если xdebug.remote_autostart установлен в false, то Xdebug проверяет указано ли название отладочной сессии в COOKIE или GET параметре. Второй вариант нужен, для того, чтобы не запускать Xdebug для всех вызовов скрипта, а только для случаев когда это необходимо. Для установки упомянутой COOKIE/GET чаще всего используются дополнительные расширения браузера, позволяющую делать это всего одним нажатием кнопки (гуглите firefox/chrome + xdebug).
    Дабы не усложнять будем рассматривать установку remote_autostart = true
  5. Теперь Xdebug-у, нужно установить соединение с вашей IDE, чтобы передавать данные туда. Данные передаются по протоколу DBGP (указывается в настройках). На схеме, это вторая стрелка сверху. Прежде чем соединение будет установлено, XDebug-у нужно знать с каким конкретно IP адресом (т.е. адресом вашей машины) ему нужно связываться. Для этого, проверяется установлена ли опция xdebug.remote_connect_back в true. Если это так, то будет использоваться IP адрес откуда пришел запрос к веб-серверу (на схеме это HTTP Request). Если xdebug.remote_connect_back будет false, то xdebug будет использовать адрес указанный в параметре xdebug.remote_host. Так же для подключения ему необходимо знать порт к которому нужно подключиться, за это отвечает опция xdebug.remote_port, по-умолчанию это 9000.
  6. Теперь, XDebug может устанавливать соединение, но, чтобы ему ответила ваша IDE необходимо чтобы она запустила сервер, к которому и будет подключаться XDebug. Поэтому, открываем свою IDE, гуглим как она конфигурируется и задаем ей те же настройки, т.е. протокол dbgp и порт 9000. Зачастую все настройки уже заданны и Вам ничего настраивать больше не нужно. Но, одних настроек недостаточно. Нужно, запустить сервер отладки. В разных IDE это делаетя по разному, в основном будет кнопка с надписью похожей на "Start Listening for PHP Connections". Основная суть этого пункта, в том, что еще до того как перейти по url в браузере или выполнить скрипт в консоли, вам нужно запустить отладочный сервер в вашей IDE, иначе XDebug-у некуда будет подключаться. Так же, хоть это всего скорее и очевидно, но уточню, что запуск отладочного сервера никак не зависит от PHP или XDebug-а (ну кроме того, что из них должны прийти запросы позже), т.е. вы можете сделать это даже без установленного xdebug-а. Проверить что отладочный сервер запущен,  можно такой командой
    sudo lsof -i -P -n | grep 9000

    тут 9000 - это указанный порт. Если он запущен, вы увидите что-то вроде

    java      18057           vitto  188u  IPv4 1407270      0t0  TCP *:9000 (LISTEN)
    
  7. Окей, IDE настроена, отладочный сервер в ней включен и ждет на порту 9000. Теперь в IDE ставите точку останова в вашем скрипте. Переходите по URL или выполняете скрипт в консоли. В случае с URL запрос идет к веб-серверу, затем к PHP, PHP выполняет XDebug, XDebug соединяется с отладочным сервером запущенным на указанном IP на порту 9000 в IDE и они начинают общение. Далее, если была установлена точка останова, то скрипт прерывается в указанном месте и вашей IDE передаются значение переменных в этом месте. Теперь из IDE с помощью кнопок "продолжить выполнение" и "продолжить выполнение внутри функции" можно делать отладку и отслеживать значение нужных переменных на каждом шаге выполнения.
  8. Как только дело дойдет до вывода данных, они начнут отправляться в браузер, именно это и есть последняя стрелка на схеме "Http Response"

Как установить XDebug

Прежде всего, нужно упомянуть официальный сайт XDebug-а: https://xdebug.org

Установку буду рассматривать для Ubuntu, для остальных систем она не сильно отличается.

Итак, наиболее простой способ установки, это выполнить

sudo apt-get install xdebug

немного сложнее, это сперва установить PECL, а затем выполнить установку xdebug

apt-get install php-pear php-dev
pecl install xdebug

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

  • Mod Apache: /etc/php/7.0/apache2/conf.d/xdebug.ini  ->  /etc/php/7.0/mods-available/xdebug.ini
  • PHP-FPM: /etc/php/7.0/fpm/conf.d/xdebug.ini  ->  /etc/php/7.0/mods-available/xdebug.ini
  • CLI: /etc/php/7.0/cli/conf.d/xdebug.ini  ->  /etc/php/7.0/mods-available/xdebug.ini

которые ссылаются на один и тот же файл: /etc/php/7.0/mods-available/xdebug.ini

Если у Вас нет этих конфиг файлов, то нужно или создать ссылку на основной или создать сами файлы.

Минимальное содержание это файла, это загрузка библиотеки

zend_extension=xdebug.so

В этот же файл, добавляются другие настройки связанные с XDebug, итоговый файл у меня выглядит так:

zend_extension=xdebug.so

xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
xdebug.max_nesting_level=300
xdebug.idekey=PHPSTORM
xdebug.remote_connect_back=1
xdebug.show_error_trace=1
xdebug.remote_autostart=1
xdebug.file_link_format=phpstorm://open?%f:%l
#xdebug.remote_log="/tmp/xdebug.log"

Про эти и другие опции можно почитать в справке: https://xdebug.org/docs/basic

После каждой модификации нужно перезагружать Apache и/или PHP-FPM.

systemctl restart apache2
systemctl restart php-fpm

Протестировать установку xdebug в Apache/PHP-FPM можно создав скрипт с таким содержимым и открыв его в веб-брауезер

<?php
phpinfo();

При правильной установке, вы должны увидеть соответствующую секцию c параметрами XDebug.

Для проверки в консоле, достаточно выполнть

php -v

в результате Вы получите надпись о том, что Xdebug установлен и его версию

PHP 7.0.33-7+ubuntu18.04.1+deb.sury.org+1 (cli) (built: May  3 2019 09:57:22) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.33-7+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2017, by Zend Technologies
    with Xdebug v2.7.1, Copyright (c) 2002-2019, by Derick Rethans

для просмотра опций, выполните

php -i | grep xdebug

если все установлено правильно выведутся все опции, что-то вроде

etc/php/7.0/cli/conf.d/20-xdebug.ini,
xdebug
xdebug support => enabled
xdebug.auto_trace => Off => Off
xdebug.cli_color => 0 => 0
xdebug.collect_assignments => Off => Off
xdebug.collect_includes => On => On
...

Настройка PHPStorm и Xedebug

PHPStorm настроен из коробки, поэтому особенно настраивать ничего не нужно. Но, на всякий случай напишу, что конфигурцаия находится в настройках по вот такому пути:

File > Settings > Languages & Frameworks > PHP > Debug

Там, согласно нашему примеру, нужно установить Port:9000 и галочки:

[+] Can accept external connections
[+] Force break at first line when no path mapping specified
[+] Force break at first line when a script is outside the project

Так же, тут я хочу упомянуть одну довольно странную историю: на домашнем ПК, я все никак не мог заставить PHPStorm работать c XDebug. Все делал как всегда, но на работе "все работало", а дома нет. При этом, в Eclipse и Netbeans все работало как надо. В общем, дождался я новой версии шторма, установил ее и все начало работать, без каких-либо дополнительных настроек. Мораль этой истории такая. Если Вы все сделали как надо, а с вашей IDE XDebug не работает, то проверьте с другой IDE, например с Eclipse. Если не работает и там, значит проблема в Xdebug. Если там работает, а например, в PHPStorm нет, то проблему надо исктаь в нем.

Заключение

Я понимаю, что для новичка эта статья выглядит примерно так

Как нарисовать сову

На самом деле настроить Xdebug не очень сложно. Нужно лишь понять как он взаимодействует с вашим редактором (IDE), именно этому я и хотел уделить внимание.

Разобравшись с ним однажды, вы точно будете его постоянно использовать. Так что, даже если у вас не получилось настроить его с первого раза, рекомендую не отчаиваться и попытаться снова.

Полезные видео про настройку XDebug

Evgeniy Kuvshinov - Отладка в PHP с помощью xdebug, docker, phpstorm, netbeans

Разван Ломов - Xdebug + PhpStorm

Категории: IDE PHP
Тэги: phpxdebug