During debugging, the single most important thing is knowing what value variables hold, this is what tell stories of change and points at culprits in your hair-pulling journey. In this post, I attempt to visit ways PHP developers tackle this debugging problem, hopefully we’ll learn new things and reduce the number of deaths caused by disappearing values and misbehaving operations.
If we were to assign hats to different methods of peeking at what’s really going on under the hood, the
var_dump() style will wear a fireman’s hat. Mostly, because users of this style are almost always quenching fires. Though we have some PHP programmers who simply don’t know ~~a better~~ any other ways or hats - if you like. Nevertheless, it should be noted that this can sometimes be the fastest way to get the job done.
var_dump($suspect); is strewn across the battle field, some users follow that up with
exit() while others shamelessly type
die($suspect); for reasons best known to them.
As at time of writing
add(int $first, int $second) will be a more correct way of achieving this. But, for the sake of this demonstration let’s us this dirtier way.
Now, assuming we call this function with real values, like so
add(2.2, 3.0); our result will be 5. If we didn’t know why we were getting wrong results when we pass real values, we’ll call
vardump() passing variables we suspect.
If that seems in order, we’ll move the call to
vardump() further down. We’ll keep moving them till we find the culprit - this moving of the
vardump() call - akin to setting breakpoints - could be copy-paste or cut-paste, what is important is knowing the state of the program.
Surely, you can already see the cons of this method of debugging. If you need to check any state, you must pass exactly what you want to the function, if you do change your mind about what you want to check, you’ll modify the “breakpoint” to reflect your change of mind. What if you forget to remove
vardump($DBName, $DBUser, $DBPass); or something worse?
This is an interactive debugger available from PHP5.4+, sporting many features, short list of those I use very frequently: - breakpoints (well, should be expected, duur) - print (printing current codes being debugged - current line, method, function, current stack, class etc.) - watch (setting watch points on variables) - info (shows information about loaded classes, methods, functions, methods, variables, constants etc.)
So, armed with this new tool let’s debug the
add() function from before. We’ll begin by setting out execution context (the code we want to bebug)
exec /path/to/phpfile (this is within the phpdbg console). Then we can set breakpoints, format is
break <line number>. So, we are going to skip setting single breakpoints and moving them around. We’ll set as many points as we need (afterall, we aren’t making changes to our code).
Next run our php file using the
run command, you will notice that we’ve hit our first breakpoint as this halts the running of our code with the prompt:
So, at our first breakpoint we can use to
info command to see all information available, don’t be fazed by all the information there it shows all constants, classes and functions within your current scope (I hope that makes complete sense). Typing
info vars shows exactly what we want at this time, details (type, name, address and value) our variables
$second and we can see the problem immediately -
$first holds a value of
2 instead of
2.2. To do the same for the next line of code, use the
step command to step to the next breakpoint.
There are so many other things this debugger can help you with, see full doc.
IDE integration for phpdbg is not really up there, this sort of limits it’s use in large and more demanding projects. Also, phpdbg is not particularly suitable for debugging Apache or FPM processes, there is a better tool for that (xdebug). But, for command line debugging it is not only sufficient, phpdbg is also very easy to use - added incentive, no setup required, it ships with Php.
How I use it? Usually I debug unit tests, in this case, it is very easy to use phpdbg - I even think it’s superior to XDebug when debugging from the command line.
XDebug generally shines in Remote Host Debugging. Being quite robust and feature rich in addition to mature IDE integration (PhpStorm, Visual Studio Code, Sublime Text etc), this means it is the most used debugger for Php though it is a third party extension. So, when working from an IDE or any other text editor (with XDebug integration) setting breakpoints is a matter of clicking the gutter (just left of the line number depending on IDE/Text Editor). Note that installation for specific environment must have been completed (remote debugging has to be enabled if you intend to do web development). This installation process is beyond the scope of this post (click here for installation instructions).
Writing and running our original code in Visual Studio Code (After installation and complete configuration) is a simple matter of setting clicking the gutter beside lines 5, 6 and 7.
Now, running your script while Visual Studio code is listening for XDebug will cause VS Code to break into your source code at the breakpoints. Information about variables, call stack and so on can be found on the left pane, see screenshot.
Use what works best for you, just pick carefully what works for your use case. Also note that phpdbg ships with Php, XDebug doesn’t (Don’t debug on a production server - read don’t install XDebug on your production server).