WordPress Debugging

On-screen debugging output, writing errors to a log file, real time monitoring of the debug log

In general, error logging should be enabled in the development environment and disabled in production environments.

To enable WordPress error reporting to the browser, and to enable error logging to file, add the following lines to wp-config.php:

<?php
// Enable error reporting output to browser. Default value is false.
 define( 'WP_DEBUG', true );
// log errors to `/wp-content/debug.log`. Useful when debugging code that does not output to browser.
define('WP_DEBUG_LOG', true);

Enabling WP_DEBUG will cause all PHP errors, notices and warnings to be displayed. This is likely to modify the default behavior of PHP which only displays fatal errors and/or shows a white screen of death when errors are reached.

Showing all PHP notices and warnings often results in error messages for things that don’t seem broken, but do not follow proper data validation conventions inside PHP. These warnings are easy to fix once the relevant code has been identified, and the resulting code is almost always more bug-resistant and easier to maintain.

– WordPress Codex

Browser Debugging

Enabling WP_DEBUG provides useful error messages rather than the “white screen of death”.

Even when code is not broken, debugging output will highlight deprecated WordPress functions and other problems.

Logging

The WP_DEBUG_LOG option is very useful for situations that do not involve output to the browser – for example AJAX requests. It is also useful when debugging classes or functions that pass data to other scripts.

You can make code write to the debug log using the PHP error_log() function.

For example, in the following code fragment, taken from a class method, the $column_name variable is output to the error log – so that we can check we’re getting the right values at this point in the programme:

<?php

...

 // Headings
 // -------------------------------------------------------------------------
 foreach ( $wpdb->get_col( "DESC " . $table_name, 0 ) as $column_name ) {

 // output $column_name to the error log
 error_log( $column_name );
 $csv_output = $csv_output . $column_name . $this->delimiter;

 }

 

Monitoring The Log File

The log file must be owned by the server process – in the case of Ubuntu, this is ‘www-data’.

I often chown ownership back and forth for various reasons – so wrong ownership of debug.log often trips me up. When developing a theme or plugin, it’s probably best to create an alias giving ownership of just the theme or plugin directory to $USER – leaving the rest of the development site owned by www-data.

It can be useful to view the debug.log in realtime. The tail utility with the -f (follow) option is good for this.

Open a shell terminal (BASH) and add the following:

tail -f /path/to/debug.log

This outputs the last 10 lines of debug.log, and the output data will be appended if the file grows – so you’ll have a realtime monitor of the debug log in your terminal. If you need more lines, append the -n flag to the tail command. To output the last 50 lines of the log file:

tail -f /path/to/debug.log -n 50

Alternatively, open debug.log in a text editor (e.g. gedit). After running your code, activate the editor window – under Ubuntu at least you’ll see a “changed on disk” notification – reloading the file will show the new log output.

User Roles & Capabilities

It can sometimes be useful to output user capabilities onto the page, especially when you are fine tuning access for custom user roles.

A combination of the ‘get_role()’ WordPress function and ‘var_dump()’ is useful in this case:


<?php
// Debug: Dump user capabilities for 'student' custom user role

$user_role = 'student';
$user_caps = get_role( $user_role );
echo "<pre><h3>$user_role Caps</h3>";
var_dump( $user_caps );
echo "</pre>";

You might also need to check available metadata for a given user:


<?php
// Debug: Dump usermeta

$student_meta = get_user_meta( $current_user_id );
echo "<pre><h2>usermeta</h2>";
var_dump( $student_meta );
echo "</pre>";