WP_DEBUG
in the config file, but some don’t know there are way more possibilities with WordPress and PHP in general. In this article, I’m going to show you some tips and tricks that I use when debugging WordPress plugins and themes.The Basics
Like I said, WP_DEBUG is the common debug flag we use when working with WordPress. You normally see something like this in the wp-config file define( 'WP_DEBUG', 'true' );
This is what’s called a constant; it’s accessible anywhere from within WordPress itself. I, personally, use a more robust debug log, like so:
define( 'WP_DEBUG', true ); if ( WP_DEBUG ) { define ('JETPACK_DEV_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); define( 'SCRIPT_DEBUG', true ); if ( defined( 'DOING_AJAX' ) && DOING_AJAX || defined( 'DOING_CRON' ) && DOING_CRON ) { define( 'WP_DEBUG_DISPLAY', false ); @ini_set( 'display_errors', 0 ); } else { define( 'WP_DEBUG_DISPLAY', true ); } }
I know, it’s a lot to take in! So let’s break it down, shall we?
Jetpack Debug
One notable constant you’ll see in this snippet is define( 'JETPACK_DEV_DEBUG', true );
This constant sets Jetpack into debug mode in your development environment. If your project doesn’t use Jetpack, you may not need this one, but Jetpack is a daily thing so I always have it.
Logging
The next is WP_DEBUG_LOG
, this is an absolute MUST if you are debugging in WordPress. What this does is provide a debug.log file in your /wp-content/
directory for you to read. What I like to do, since I have more than one monitor, is to open a terminal and dedicate one monitor to the debug file. To do this, if you’re not familiar, you can tail the file like so: tail -f wp-content/debug.log
this will stream the file to your terminal. Every time a new error shows up, you’ll see it.
If you’re new to the command line, and have a Mac, a simple process you can follow is:
- Type
tail -f
in your terminal - Navigate to the wp-content directory of the project you’re working on. If there is no debug.log file there, simply create it.
- Once the debug.log file exists, drag it to your terminal window to right after the
tail -f
you typed. This will output the full file path location in terminal - Hit
enter
. Once you do that, you’ll see when items get added to the log on the fly. - To stop the tail output, hit
ctrl + c
on your keyboard
Script Debugging
I don’t see this a lot, but it’s VERY useful if you’re working with JavaScript, as well as forcing WordPress and/or your plugins/themes to load non-minified files. Another great thing you can do is use script debug to pass to your JavaScript–so you can keep your debug code inside your script without having to re-save it. This is especially useful with projects that use grunt and require you to re-compile your scripts. Here’s the snippet:
<?php // Using Script Debug to load non-minified scripts $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_enqueue_script( 'my_awesome_script', "my_inc_dir/javascript_file{$min}.js", array( 'jquery' ), '0.1.0', true ); // Using script debug to log data in a javascript file wp_localize_script( 'my_awesome_script', 'mas_obj', array( // Set to true if debug is enabled, false otherwise 'is_debug' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? true : false, ) ); ?> <script type="text/javascript"> // Try and grab our object, if not make one. var our_script_l10n = window.mas_obj || {}; // Check if debug is available/true if ( our_script_l10n.is_debug ) { // We have debug on for our script, so alert the user. alert( 'Debug Works' ); } </script>
A good way of handling minimized vs expanded scripts is to take a look at the first section when you queue it up. Most of the time, when developing, you want to make 100% sure you can debug your scripts, and if your browser throws an error on a minimized script…well, we all know how much of a pain that is.
Next up is script localization. Looking at lines 8-11, you can see that I’m passing an is_debug variable to the script we just queued up. This will allow you (as in the lower section) to check against that and debug ONLY when that’s available. By doing this, and given that most production servers don’t use the debug constant, you will prevent end-users from seeing your debug output on the production site.
To Display or Not to Display?
That is the question, right? This all comes down to preference really. In the first section in the debug snippet (the first one on the post) you’ll see a check for defined( 'DOING_AJAX' )
as well as defined( 'DOING_CRON' ).
This is to make sure that if an AJAX call or cron job is running, we don’t accidentally drop debug data into these responses. The section you want to pay attention to is in the else portion of the conditional. This is where you make your decision–pretty simple though! Just true or false.
Since I stream the debug log on my second monitor, I set this to false, but for the purpose of this blog post, I’ve set it to true–just in case you decided to copy/paste the snippet without reading the actual information attached.
Advanced Debugging
I’m not sure this is really considered advanced debugging, but it does require a knowledge of built-in PHP Magic Constants to grasp, as well as the error_log()
function that’s built into PHP. Throughout your development career, you will need to debug an entire class, large function, or a whole file, usually because there’s no data being output to the debug log.
This is definitely where these magic constants come in handy. Magic constants are great for more than just debugging, but my focus here is how I use these in a debugging environment. Here are a few examples that should get you on the right track:
<?php class My_Class { public function my_func() { // We can error log our data here. error_log( __LINE__ ); // outputs 6 // Or we can also log which method we're in error_log( __METHOD__ ); // outputs My_Class::my_func } } function my_function() { // With functions, you can also log their function name error_log( __FUNCTION__ ); // outputs my_function } function log_this(){ // You can also combine them, here is a basic example error_log( sprintf( '%s - %s::%d', date( 'F j Y', time() ), __FUNCTION__, __LINE__ ) ); // Will output something like August 1, 2015 - log_this::21 }
Here’s a quick rundown for those of you who don’t want to click through the link:
- __FUNCTION__ – Returns a string, containing the name of the function the constant is used within.
- __METHOD__ – Usable only within classes, this returns a string containing the method & class name the constant is used within.
- __CLASS__ – Though not shown in the example, this will return a string containing the class name the constant is in.
- __LINE__ – Last but not least is LINE (possibly my most used)–it returns the line number that it is currently on.
Line for me, is the most common, when debugging larger files, I tend to just spam error_log( __LINE__ )
throughout and see which ones return data and which ones are skipped. This is doubly helpful with huge files with a lot of conditionals. Though I caution the use of __LINE__
within loops, as you will undoubtedly get confused. You will also want to make sure you remove the error logs if you didn’t put them in a debug conditional check, as stated in the previous section.
Conclusion
When writing themes & plugins, it is your responsibility to make sure your code is clean and not junking up the debug log or your PHP error_log
file. There’s nothing more depressing to a developer than getting flooded with messages because the previous developer didn’t use debugging at all. Your whole team should be using debugging–developers and designers alike. The more eyes you have on a site, the more chances you’ll get to find issues…unless you write perfect code, of course.
No one is perfect! We all break things, but without looking at our debug logs, we may never see it.
Have any questions or insight about debugging? Throw it in the comments.