Simple Debugging with WordPress

For simple WordPress theme development, what is the first thing most PHP developers do to troubleshoot problems?

print_r( $post );
die();

One the statements are in place, the programmer refreshes the page and looks at the source to view a nicely indented array or object. Next they comment out the print_r and die statements, change some lines, and try the code again. If it fails, they are back to square one and in go the print_r,echo and die statements so the brutal cycle can begin again.

We know these methods partially work (who hasn’t done the above during a PHP project!), but we also know they are less than optimal. Is there a better way?

WordPress Debug Mode

WordPress offers quite a few ways to enable and customize a debug mode while developing. To enable debug mode, you want to define WP_DEBUG as true in your wp-config.php. Here is the complete code block I suggest you use. We will look at the individual parts shortly. Place this in your wp-config.php file after the lines that define the database variables. Be sure to change development_user to be your development database user name:

@ini_set('display_errors',0);
if( 'development_user' === DB_USER ){
  define('WP_DEBUG',         true);  // Turn debugging ON
  define('WP_DEBUG_DISPLAY', false); // Turn forced display OFF
  define('WP_DEBUG_LOG',     true);  // Turn logging to wp-content/debug.log ON
}

display_errors

The first line in our code block turns off the display of errors, regardless of php.ini or .htaccess settings to the contrary. This is important because though WordPress can force the display of errors to be on, it won’t force them to be off if display_errors is already turned on.

Testing for local vs. production

There are probably fifty ways of doing this part, so use a method that works for you. In my environments, my local development database rarely if ever has the same user name as the production database. Simply checking what I expect the local user name to be against what is defined in DB_USER is a simple way of knowing if the files are on the development or production servers.

WP_DEBUG

This is the most important constant as it determines if WordPress will use any of the other debugging constants. Thankfully it is quite simple. If set to true, debug mode is turned on. If undefined or set to false, debug mode is kept off.

WP_DEBUG_DISPLAY

This constant confused me at first, but it is actually quite simple. If set to true, it will override the current display_errors configuration setting and turn it on. However, if set to false it will not turn off display_errors. This setting is simply an override. This is the reason we turn display_errors off before setting any of these constants.

Set this constant to true if you want to see errors displayed in your browser when they occur. Keep in mind this will sometimes complicate errors because once at least one error has been written to the page, all redirect requests will fail. This is because the header information can no longer be modified once content is sent, and a displayed error counts as content.

WP_DEBUG_LOG

This constant is the whole reason I found the WordPress debug methods so helpful. Set this constant to true and WordPress will set up PHP to write to an error log in wp-content/debug.log. Sadly you can’t specify a different file location that is not in the content folder, but at least you know where it is!

Note: because this is written to a public directly, be extremely careful not to upload the log by mistake. Additionally, if you run WP_DEBUG on a production server, do so only for immediate troubleshooting then turn it off and remove wp-content/debug.log.

Leveraging WP_DEBUG

In addition to PHP errors being sent to debug.log we can also send our own output using the error_log PHP function. The only problem with this, is even in production mode your errors will still most likely be written to a PHP log; it just won’t be debug.log. Because of this, its a good idea to provide a wrapper function to handle the logging for your theme or plugin.

Place the following code in your functions.php in your theme, or in the plugin file for your WordPress plugin:

if(!function_exists('_log')){
  function _log( $message ) {
    if( WP_DEBUG === true ){
      if( is_array( $message ) || is_object( $message ) ){
        error_log( print_r( $message, true ) );
      } else {
        error_log( $message );
      }
    }
  }
}

Feel free to expand on this function if it doesn’t exactly meet your needs, but the concept is simple: Centralize all your log calls to use your custom function. Then, in that _log function, only output the message if WP_DEBUG is set to true. There is no reason to test if WP_DEBUG has been defined because as soon as wp-settings.php is processed, WP_DEBUG will be defined, even if it wasn’t already defined in wp-config.php.

This particular _log snippet will call a print_r on arrays and objects passed to the function for simple debugging.

Trying it Out

If you have followed these steps, you can run a quick test by adding these lines into your header.php file in your theme folder:

_log('Testing the error message logging');
_log(array('it' => 'works'));

After refreshing your page once, you should see a newly created debug.php file with a few lines of output. Use any log viewing utility that supports tailing the file for maximum productivity. On Mac, Unix and Linux systems, you can use this command from the main directory of your site:

tail -f wp-content/debug.log

More Solutions

If you are looking for a more interactive console for debugging, be sure to look at our review on the WordPress Console.

What about you? If you didn’t already know about this built in WordPress feature, what methods did you come up with to make debugging WordPress easier? Please leave us your tips in the comments below!

Doug Neiner is an Editor at Fuel Your Coding and an official member of the jQuery Team. He is addicted to new technology, and specifically loves spending time with WordPress, Ruby on Rails and jQuery. Learn more via twitter or his Google Profile.

 

If you liked this article, please help spread the news on the following sites:

  • Bump It
  • Blend It
  • Bookmark on Delicious
  • Stumble It
  • Float This
  • Reddit This
  • Share on FriendFeed
  • Clip to Evernote