PHP Debugging Crash Course

PHP, an old relic that was popular at the turn of the century, still chugs on in various obscure codebases and legacy systems. PHP seems like it is going the way of COBOL: A powerful, specialized set of codebases in maintenance will need ongoing help for decades to come.

One of the most frustrating things to work with is that PHP is debugging and introspection. That’s because a complex patchwork of systems can make it very difficult to see what’s going on in a large PHP app. Mostly, these systems are implemented by well-meaning developers who don’t realize the precariousness of swallowed errors in codebases. Often developers use try / catch magic to make errors “go away,” but really they make future development much more difficult by hiding errors.

Unlike most modern frameworks, PHP only logs requests through your NGINX or Apache logs. The print, die, and var_dump all output their results to the HTML content, and not the actual system logs. (Syslog does output to the system log as you’d expect.)

The php.ini File

The Error Log File

Quick Tips

Command line PHP.

When on the command line, your PHP interpreter may have different ini settings and error log settings.

This will tell you where the error log is:

php -r "var_dump(ini_get('error_log'));"

This will tell you where the php.ini file.

php -r "var_dump(php_ini_loaded_file());"

Standard PHP Debugging Tools

var_dump($foo)dumps the variable type and value to the screen
print_r($foo) and
print_r($foo, true) 
prints the variable value in human-readable form to stdoutWithout a second a parameter (or a false), the result will be printed to the output. With true as the second parameter, the result gets returned to the calling code.
get_defined_vars()gets all the defined variables including built-ins and custom variables (print_r to view them)
debug_zval_dump($var) dumps the variable with its reference counts. This is useful when there are multiple paths to update a single reference
debug_print_backtrace() prints a backtrace that shows the current function call-chain.
debug_backtrace()gets the backtrace. You can print_r, log it to a file, or send it to a logging endpoint asynchronously.
file_put_contentsUsing this technique you can simulate something similar to making your own log system.

XDEBUG

Error reporting level

• use the php.ini file if you have access to it

• if you don’t, try setting it in htaccess configuration

• If neither of these is possible, you can do it in runtime programmatically

php.ini File Settings

error_reportinglevel of logging
E_NOTICE
display_errors
display_startup_errorsused for debugging startup errors
error_log
log_errors

Some PHP Magic To Avoid

https://www.php.net/manual/en/function.register-shutdown-function.php

https://www.php.net/manual/en/function.set-exception-handler.php

https://www.php.net/manual/en/function.set-error-handler.php

Logging

Logging is a beast in PHP because it doesn’t naturally log in a sensible way.

https://github.com/Seldaek/monolog