16 июня 2016 в 11:55

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

PHP*
Иногда приходится работать с сервером через «кучу» файерволов, 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-инструментами по новому проекту позволяет быстро понять его архитектуру для случая когда нет документации, а проект разрабатывался одновременно большим количеством сотрудников.
Евгений @bizzonaru
карма
9,0
рейтинг 0,0
Пользователь
Самое читаемое Разработка

Комментарии (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;», что гораздо проще и быстрее.
    • 0
      :-)

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