How to Debug PHP Errors

Debugging PHP errors in a production environment can be one of the single most frustrating experiences as a developer. More often than not, the error reports are vague, and identifying the underlying causes can be difficult at best. That said, there are a few common steps that can be followed towards identifying and resolving errors that crop up in production.

Debugging PHP Errors

Step 1: Increase the log level

More information is always better. Using the methods described in Where are PHP Errors Logged?, the first step towards diagnosing any issue is to increase the log level. This allows you to see everything that is happening before and after a problem occurs. There is a good chance that the problems you are experiencing have warnings or messages associated with them that don't necessarily make it into the log files by default.

Step 2: Retain logs

Once you've increased the log level, the next step is to start retaining logs. This can be done through any number of log aggregation platforms, and allows you to start establishing a timeline of events without worrying about the log files being rolled over.

Step 3: Attempt to replicate circumstances

Once you've determined the log lines that relate to the problem at hand, the next step is to attempt to replicate the circumstances of the error in a development environment. Before we can do this, we first need to establish some testing guidelines. This involves doing things like mimicking the production database, the user accounts involved, and even the operating system. Everything is fair game here.

Step 4: Test assumptions

Once you've established the circumstances that you think might throw the exception or error you are hunting down, it's time to test them. Never test exceptions in production. Development and staging environments are designed to be breakable without any impact on the end-users, so always always always try to break your code in a safe environment.

Step 5: Adjust test parameters and try again

If you were unable to replicate the problem in Step 4, then it's back to the drawing board. Not every error is easy to reproduce, and may have time-based constraints or something else making it difficult to replicate in a non-production environment. Jump back to Step 3, adjust your test parameters, and try it all over again.

What is a stack trace?

Whenever exceptions are thrown, a stack trace is usually included. But, what is a stack trace? In essence, it is a rundown of every file and function that is called leading up to the error. To be clear, a stack trace doesn't include the files and functions that are touched before the error occurred, only the chain of methods that are called as the error happened. This allows you to "trace" the "stack" of operations that are performed when an error happened in order to identify exactly what went wrong, and where.

As an example, let's take a look at the stack trace that is returned from the following (incredibly simplistic) code:

do_the_thing();

function do_the_thing() {
  throw new \Exception("a thing happened!");
}

When dothething() is executed, an exception is immediately thrown. This results in the following stack trace:

Fatal error: Uncaught Exception: a thing happened! in test.php:6
Stack trace:
#0 test.php(3): do_the_thing()
#1 {main}
  thrown in test.php on line 6

As you can see, rather than simply returning the exception message, reading the stack trace in reverse order shows that the exception was thrown on line 6, but was triggered by a call to do_the_thing() on line 3. For more complicated stack traces, this can be invaluable as it gives us a lot of post-mortem information.

A brief introduction to Xdebug

While debugging in development can be difficult to do, Xdebug is a popular tool to help identify exactly what is happening as a piece of code executes. Containing a single-step debugger that allows you to interact directly with running PHP scripts, Xdebug is an excellent way to deal with highly complex and nuanced issues without having to resort to dangerous var_dump() and exit calls.

Example var_dump/exit call

IDE integrations

While Xdebug is an incredibly powerful tool that can be used for more than just stepping through code, one of the more impressive aspects of it is the numerous IDE integrations that exist. These integrations give you the ability to diagnose problems with your code from directly within your editor, allowing you to test and fix problems in the environment you are most comfortable with.

Visual Studio Code XDebug Integration

Identifying patterns using Rollbar

Too often, debugging errors in a PHP application comes down to the amount of information you can eke out of your logs. Rollbar offers a better way because it empowers you to not only identify what is happening, but when, where, to whom, and how often. Rather than having to sort through pages of raw text logs, Rollbar aggregates data from individual exceptions and errors and creates a dashboard with as much information as possible for analyzing these issues.

When properly configured, these exceptions can be tied directly to user accounts, and tracked over time across an easy-to-read graph—with deployment markers to boot. While this doesn't necessarily tell you exactly what an issue is, it comes as close as possible to doing so by providing you with more information than you could possibly ask for.

Occurrences

Whenever an exception is thrown during the course of an HTTP request, the request details are tracked alongside any additional information—such as the browser and operating system. This gives you the ability to identify any potential issues that could be related to specific systems, or even track down offending request parameters.

Suspected Deploy

If you are tracking deployments within Rollbar, then identifying which deployment might have been responsible for a new error or exception is as straightforward as possible—so straightforward, in fact, that Rollbar does the work for you.

Source Control Integration

When a Rollbar project is linked to a repository in GitHub, Bitbucket, or GitLab, any file references in a stack trace are automatically linked directly out to the offending file in the linked repository.