Recently I’ve had several discussions with colleagues asking me for the debugging practices that I use. I try to constantly enhance my workflow, resources and improve the quality of my work by speeding up the process of narrowing down the possible reasons for a bug or a feature limitation. Speaking WordPress-wise, I’ll list a couple of things that I consider important. Some of them are more than obvious, but somehow people misuse them or forget about them at a moment of crisis (so to speak).
Before you start: always do backups. Debug your web application locally, test properly and ensure that everything is on set before deploying to the real server. Best practices teach that a local server -> staging/dev server -> production server is a good setup to prevent the obvious error of hitting the live website.
I’ve been using plain text editors (vim included) for a while, but usually only for remote/small changes. I rely on a IDE for better control over the codebase and the relations. I’m an Eclipse user (naturally evolved after several years in the Java world) but you could also check out NetBeans, Sublime, PhpStorm, Komodo or anything else with more capabilities. Using an IDE helps you to set up an easy connection between the codebase and a version control, debugger, (S)FTP and use a number of function suggestions and PHPDoc comments while developing and browsing the code. Xdebug or the Zend debugger are also a crucial part. Debugging with echo or var_dump (or console.log/alert) is a quickie for one-liners, but a serious workflow iteration processing requires a debugger.
I’ve been using a number of separate plugins, most of which are already listed on the Developer plugin by Automattic, along with other best practices. It reminds you about setting WP_DEBUG and other constants in your wp-config file, as well as install environment testing plugins. In addition to the plugins listed over there, I you may also find the following useful:
Scribu has made a good job of outlining the workflow for troubleshooting. You need to limit the options for a bug to happen. Normally it narrows down to 2 steps, iterated and expressed depending on the scenario:
- disable plugins one by one and see if one of the plugins acts differently on the site when on/off
- switch the theme
Sooner or later the problem disappears when plugins are disabled or the theme is gone. If that’s not the case, you should consider whether anything you have done directly on the database (custom changes) or the file structure (like manually editing WP-files or updating the core) is causing the issue. Sometimes WordPress core updates introduce new changes and deprecates existing functions so a theme/plugin could be affected by that.
Once you have figured out what is causing the problem, you will have to find the reason for the bug.
- Try to find a repeatable context for the action, like a specific page where it occurs, or a number of pages. Find out if it happens in the backend (admin area), the frontend or both.
- See if you could find any errors in the logging plugins or the error_log file – they usually come up with a stacktrace telling you the origin of the error including a filename and a line number. If you happen to narrow the context, you would be able to find a common problem area – a piece of code that exists in the problematic pages and not in all the others. It will help you read fewer lines of code and debug a smaller chunk of the entire pack.
- For PHP errors, make sure you’re keeping up to date with your code style and conventions. Double check your functions don’t reappear (name collision) by being registered from another/plugin or a theme.
- Use prefixes or better OOP classes with a proper hierarchy (even namespaces!).
- Make sure your imports are included in the right order. Do you register everything on the correct hook? Some actions such as script embedding should be registered on the right hook depending on the context.
- If you need frontend scripts, do use wp_enqueue_scripts. If you wonder why is the admin looking clumsy, go for admin_enqueue_scripts.
- If you have ajax calls, make sure they’re registered properly, with WP AJAX hooks, passing the action properly. Also, some data might be lost due to the actual request, so just keep that in mind (it’s running in a different context, different time, so the environment could vary depending on that).
- Go through the plugin core and beware of automagic. Some plugins try to run the principle of ‘convention over configuration’, which means that the configuration could be omitted if you follow a specific guidelines. It’s a common thing for frameworks such as Django or Rails-alike projects, keeping the same naming convention (files, functions) and directory structure for placing files. There is no verbose code stating that something is loaded – it just if it is named like that.
- A similar approach from the WordPress context is the templating structure – you have page.php that covers all pages, index.php, archive.php and so on. If archive.php is missing, it would fallback to index.php. It’s not obvious, you just need to know the hierarchy and the chain of invocations. Some plugins define extra routes, additional context paths, AJAX rerouters and so on that make things complex.
Themes have a good process for a proper and painless interaction with WordPress core. However, some theme authors intentionally (or rather not) include custom implementations for their specific scenario that doesn’t behave well with all common cases. A common example is using timthumb for image management – not only is it insecure and heavy, but it’s inflexible.
Knowing the template hierarchy, try the following:
- See if the template you’re after is actually the one running the code that’s broken.
- Beware of actions and filters that might be defined in functions.php or in a third party plugin that could ruin your straightforward thinking.
- If data is not displayed at all (or a wrong data), check your query.
- Avoid using get_posts or query_posts in a complex environment (or ever), better use a custom WP_Query query and reset the postdata at the end not to interfere with other listings.
- Debug your query calls and check the output SQL code generated.
- If there is a styling problem, it’s most likely a CSS definition. The correct order of CSS statements is important, usually the latter overrides the former. However CSS selectors have priority, such as – IDs are with a higher priority than just classes, so keep that in mind (even if a . call is below, the # call might be prioritized higher).
- See if the correct stylesheet is applied on the specific page and confirm that nothing is overriding it.
- 1) enqueue jQuery (just wp_enqueue_script(‘jquery’) in wp_enqueue_scripts hook call)
- 2) use jQuery before you define the alias. Prototype is run first and the dollar sign isn’t automatically applied to a jQuery call.
For Apache and nginx there are so many configurations that could make a difference.
- If you see 5xx errors, double check your server config first with a sample file as proof of concept and then proceed to inspecting your code for anything that could lead to misunderstanding with the server configuration.
- Verify your .htaccess file in your plugin folder. There is a default one distributed with WordPress, unless you use caching plugins (or automate the caching) there is usually no reason to touch it.
- Check out your virtual hosts in the server config. Domain names could be linked to the wrong IP/port sequence or folder, or the directory could not be writeable.
- If pretty permalinks are not working, have you got mod_rewrite enabled?
- Some memory problems could be solved by increasing the PHP memory limit. You could try (in this order): wp-config.php, php.ini or .htaccess (you might have your own preferences). There are different configurations to change: server (PHP) memory, file upload size/timeout time and so on, for different activities.
Google is your best friend. Use it. If you don’t know how, it’s time to learn. And no, it’s not always straightforward. You need to learn how to select the proper phrase for searching (think about the results you’re trying to find) and eventually limit the results by the advanced filters, like: limit by location, by date, use some wildcard like site: intitle: inurl: filetype: or anything that could help you limit the billions of results. StackOverflow and the WordPress StackExchange are super helpful. Don’t forget the WordPress.org forums nettuts+, WPCandy or other WP-specific sources might help for WP-related troubles.