Отладка php функций с помощью phpdbg, как альтернатива Xdebug через IDE

    Иногда приходится работать с сервером через «кучу» файерволов, c локальным IP c репозиторием и т.д., и по этой причине довольно тяжело настроить XDebug для работы через IDE NetBeans (и прочих IDE). Приходится проще поднимать локально виртуальную машину. И если XDebug нужен лишь только для того, чтобы по быстрому ознакомиться с большим новым проектом (с кучей легаси кода) с последующей отладкой через error_log, то отлаживать отдельные скрипты довольно не всегда удобно в нем.

    Неверно срабатывают точка прерывания, лишний стек вызова подключаемых скриптов и т.д. Как вариант, для знакомства с новым проектом, можно еще настроить xhprof и по быстрому просматривать стек вызова функций на графиках при вызове того или иного скрипта. В этом случае хорошо отлавливать ошибки ненужных вызовов кучи функций в циклах, в которых нет внутри static инициализации переменной. В частности, вызовы одной и той же настройки из базы данных внутри цикла (foreach, for, while, do-while). Отличие phpdbg от выше описанных инструментов в том, что он позволяет отладить конкретно какую то функцию в логике на редкостный баг. Phpdbg это грубо говоря командный (консольный) интерфейс отладки по аналогии как в NetBeans (xdebug). Если в IDE мы кликами мышки указывает точки прерывания (breakpoint-ов), то в Phpdbg это нужно делать в виде команд.

    Приведу для примера простой код.

    <?php
    
    function EugeneKurilov() {
      $i = 10;
      for($j=0;$j<$i;$j++) {
         //echo $j;
      }
    
    }
    
    EugeneKurilov();
    
    ?>
    
    

    Для выше приведенного PHP кода, для того, чтобы начать отлаживать функцию EugeneKurilov(), необходимо выполнить команду:

    prompt> break EugeneKurilov
    [Breakpoint #0 added at EugeneKurilov]
    
    

    А затем,

    prompt> run
    [Breakpoint #0 in EugeneKurilov() at /root/dbg.php:3, hits: 1]
    >00003: function EugeneKurilov() {
     00004:   $i = 10;
     00005:   for($j=0;$j<$i;$j++) {
    
    


    Нажимая команду s (step), мы проходим по телу функции, для того, чтобы просмотреть, как меняется переменная $j, необходимо выполнить команду watch $j:

    [Breakpoint #0 in EugeneKurilov() at /root/dbg.php:3, hits: 1]
    >00003: function EugeneKurilov() {
     00004:   $i = 10;
     00005:   for($j=0;$j<$i;$j++) {
    prompt> watch $j
    [Set watchpoint on $j]
    
    
    
    И далее, нажимать s (step) для прохода.

    [Breaking on watchpoint $j]
    Old value:
    New value: 0
    >00005:   for($j=0;$j<$i;$j++) {
     00006:      //echo $j;
     00007:   }
    prompt>
    
    Old value: 0
    New value: 1
    >00005:   for($j=0;$j<$i;$j++) {
     00006:      //echo $j;
     00007:   }
    
    Old value: 9
    New value: 10
    >00005:   for($j=0;$j<$i;$j++) {
     00006:      //echo $j;
     00007:   }
    prompt> s
    [L5       0x7f9d0c088100 IS_SMALLER              $j                   $i                   ~3                   /root/dbg.php]
    [L5       0x7f9d0c088120 EXT_STMT                                                                               /root/dbg.php]
    [L5       0x7f9d0c088140 JMPNZ                   ~3                   J6                                        /root/dbg.php]
    [L9       0x7f9d0c088160 EXT_STMT                                                                               /root/dbg.php]
    >00009: }
    
    prompt> s
    [L11      0x7f9d0c0735e0 RETURN                  1                                                              /root/dbg.php]
    [Script ended normally]
    
    

    То есть довольно просто таким образом в живую просматривать как меняется значение переменной и не нужно добавлять код вроде error_log (при просмотре в логе) или echo в броузере.

    Phpdbg довольно прост (для изучения функционала необходимо ввести help) и по этой причине нет смысла описывать детально все моменты. Начиная с версии PHP 5.6 он включен по умолчанию. Моей целью данной публикации было показать альтернативный вариант отладки кода. Как показывает моя практике, проход различными debug-инструментами по новому проекту позволяет быстро понять его архитектуру для случая когда нет документации, а проект разрабатывался одновременно большим количеством сотрудников.
    Метки:
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 6
    • 0
      спасибо за интересную статью, обязательно посмотрю на этот инструмент.
      Интересует вопрос производительности, если с xdebug она падает почти в два раза, то с phpdbg, как обстоят дела?
      • 0
        Не падает вроде бы, просто своего рода shell-оболочка.
      • 0
        Инструмент интересный. Спасибо что подсказали как им пользоваться (а то давно видал что есть такая штука, но как-то пользоваться не пробовал). А теперь вопрос. Этот инструмент годен только для дебага именно каких-то «независимых функций»? Его можно использовать для дебага приложения?

        Т.к. в своей практике очень редко приходится дебажить какие-то независимые функции (обычно они достаточно маленькие и в них и без дебага все понятно.
        • 0
          Для всего приложения нет, он больше для отладки отдельного скрипта, например, библиотеки в виде классов. По крайней мере я этой особенности не увидел. Можно в нем поднимать сервер и делать удаленную отладку.
          Удобней тем, что можно ту же точку останова делать не просто по номеру строки или наименованию, а с использованием условия breakpoint-а.
          prompt> help aliases
          Below are the aliased, short versions of all supported commands
           e     exec                  set execution context
           s     step                  step through execution
           c     continue              continue execution
           r     run                   attempt execution
           u     until                 continue past the current line
           F     finish                continue past the end of the stack
           L     leave                 continue until the end of the stack
           p     print                 print something
           p e   print exec            print out the instructions in the main execution context
           p o   print opline          print out the instruction in the current opline
           p c   print class           print out the instructions in the specified class
           p m   print method          print out the instructions in the specified method
           p f   print func            print out the instructions in the specified function
           p s   print stack           print out the instructions in the current stack
           b     break                 set breakpoint
           b @   break at              specify breakpoint by location and condition
           b ~   break del             delete breakpoint by identifier number
           t     back                  show trace
           f     frame                 switch to a frame
           l     list                  lists some code
           l l   list lines            lists the specified lines
           l c   list class            lists the specified class
           l m   list method           lists the specified method
           l f   list func             lists the specified function
           i     info                  displays some informations
           i b   info break            show breakpoints
           i F   info files            show included files
           i c   info classes          show loaded classes
           i f   info funcs            show loaded classes
           i e   info error            show last error
           i d   info constants        show user defined constants
           i v   info vars             show active variables
           i g   info globals          show superglobals
           i l   info literal          show active literal constants
           i m   info memory           show memory manager stats
           X     clean                 clean the execution environment
           C     clear                 clear breakpoints
           S     set                   set phpdbg configuration
           S p   set prompt            usage: set prompt [<string>]
           S P   set pagination        usage: set pagination [<on|off>]
           S c   set color             usage: set color  <element> <color>
           S C   set colors            usage: set colors [<on|off>]
           S O   set oplog             usage: set oplog  [<output>]
           S b   set break             usage: set break id [<on|off>]
           S B   set breaks            usage: set breaks [<on|off>]
           S q   set quiet             usage: set quiet [<on|off>]
           S s   set stepping          usage: set stepping [<line|op>]
           S r   set refcount          usage: set refcount [<on|off>]
           S l   set lines             usage: set lines [<number>]
           R     register              register a function
           <     source                execute a phpdbginit
           >     export                export breaks to a .phpdbginit script
           q     quit                  exit phpdbg
           W     wait                  wait for other process
           w     watch                 set watchpoint
           w a   watch array           create watchpoint on an array
           w d   watch delete          delete watchpoint
           w r   watch recursive       create recursive watchpoints
           n     next                  step over next line
           E     eol                   set EOL
           h     help                  show help menu
          
           h a   help aliases          show alias list
          
          

          То есть инструмент, по быстрому проверить код логики.
        • +5
          Спасибо за эту поистине объёмную статью, она освещает гораздо больше ситуаций, чем малопонятный мануал.

          Обожаю этот удобный инструмент, в нем специально не сделано ничего лишнего (интеграция с IDE) чтобы пользователи не тратили своё время на расстановку брекпойнтов одним кликом богомерзкого манипулятора «мышь», а экономили его, набирая «break EugeneKurilov; run; watch $j;», что гораздо проще и быстрее.

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