WordPress Debug, Shipping Made Easy
Lately I’ve been doing a lot of work on our WordPress site, https://flomio.com, having just published our first WooCommerce plugin for sale, an EasyPost Shipping Method, but more on that later. Flomio has iterated through a bunch of site frameworks over the years, starting with Django/Python and ultimately settling on Wordpress/PHP. Each has pros/cons but what drew us to WordPress was it’s popularity among creatives. The need to keep the site fresh meant our designers had to publish content without having to depend on programmers. WordPress’s intuitive admin interface makes this possible and the many plugins available online lets non-coders add functionality without much support. From responsive themes to social sharing widgets to ecommerce to forums, all these features have helped us engage our community while still building out our products.
This flexibility comes at a price, though. The collection of random plugins we’d amassed -some more supported than others- began to breakdown as updates became necessary. I’ve been doing a lot of this clean up and since I haven’t found a one stop spot for all the debugging tricks I’m using, I figured I’d write one. If anything this post will serve as a cheat sheet for me later.
Turning on Wordpress Debug
To start getting some debug information, you’ll need to add the following lines to your WordPress wp-config.php file located in the root directory of your installation (lines may already be there):
define('WP_DEBUG', true); // Turn debugging ON
define('WP_DEBUG_DISPLAY', true); // Turn forced display ON
define('WP_DEBUG_LOG', true); // Turn logging to wp-content/debug.log ON
Once in place, these defines will begin displaying notices/errors on your site pages (WP_DEBUG_DISPLAY) and in the debug.log file located in your wp-content folder (WP_DEBUG_LOG). If this is the first time you’ve ever done this, it’s very likely that you will see a lot more issues than you would like. WordPress is notoriously capable of concealing most issues for a while before they become a problem. In our case, after months of setting up the site turning these debug features on revealed over 20 issues of varying severity. Most were deprecation notices, which can be tricky to resolve. A deprecation notice is a warning from the WordPress core framework stating that an extension or plugin is using the framework incorrectly. As the framework matures over time it’s interfaces and APIs evolve and although there’s an attempt to remain backwards compatible, there comes a time when an old methods are dropped. When this happens, a simple WordPress upgrade can break some major functionality you become dependent on. It’s important to keep taps of these notices and fix them right away. Here’s one example:
Notice: Woocommerce->nonce_field is deprecated since version 2.1! in .../woocommerce/myaccount/form-login.php line 50
You want to start addressing this issue by going to the mentioned file and line number. In my case I found it like this:
<?php $woocommerce->nonce_field('login', 'login') ?>
Now what? Well, at this point I start with Google and search for nonce_field. The results point me to the new syntax wp_nonce_field so I simply swap out line 50 with:
<?php wp_nonce_field('login', 'login') ?>
Simple right? Not quite. Turns out after doing this fixed the notice issue but also broke the login function. Uggghh. So I reverted the changed and looked at the generated HTML for the page. It revealed that the code rendered was rendering differently between changes. Aha! I noticed that the original had an id and name tag set to “_wpnonce” where as the new had it set to “login”. I then realized that the wp_nonce_field syntax called for the first argument to be the domain and the second the id/name tag. So the fix resulted in:
<?php wp_nonce_field('login', '_wpnonce') ?>
Inline Variable and Stack Dumps
Removing deprecated notices is not too bad, the hard issues to solve are when your plugins simply have bugs that are revealed only after an upgrade or some change to the site. Take the following issue that showed up in the debug.log file while trying out a free WooCommerce plugin for EasyPost, called EasyShipper:
NOTICE: wp-content/plugins/easyshipper/easypost_shipping.php:25 - Undefined index: wc_customs_value
This is one of the drawbacks of free, unsupported plugins. They can introduce cryptic errors that -when accumulated- can bring your site down. Consequently, it’s necessary to monitor and address errors sooner rather than later. Looking through the code, it seems the wc_customs_value is not set for some of the orders logged. To find out more I can dump the variable and the function call stack to the debug.log by adding the following lines just before line 25 in easypost_shipping.php:
error_log('Richard was here!'); error_log(var_export($post,1)); error_log(var_export($_POST,1)); error_log(var_export(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)));
error_log('Richard just left!');
if($_POST['wc_customs_value']){ // line 25 in easypost_shipping.php
The call to error_log pushes any text to the debug.log file and on site display. The call to var_export converts the variable to a readable string format. The debug_backtrace function captures the call stack for you to see how the error was reached. Here’s a sample output after navigating around the site:
[26-Jun-2014 22:21:52 UTC] Richard was here!
[26-Jun-2014 22:21:52 UTC]
[26-Jun-2014 22:21:52 UTC] array (
'data' => array (
'wp_autosave' => array (
'post_id' => '6162',
'post_type' => 'post',
'post_author' => '4',
'post_title' => 'Debugging WordPress, Streamlining Fulfillment',
'content' => 'Lately I\'ve been doing a lot of work on our WordPress site, https://flomio.com. Flomio has iterated through a bunch of site frameworks through the years, starting with Django/Python
:
:
'interval' => '15',
'_nonce' => '78c0339659',
'action' => 'heartbeat',
'screen_id' => 'post',
'has_focus' => 'false', )
[26-Jun-2014 22:21:52 UTC]
[26-Jun-2014 22:21:52 UTC] Richard just left!
I left out some of the $_POST dump for brevity, but you can see that $post and the debug_backtrace calls returned nothing. You also should note that the actual $_POST dump is for this blog post that I’m writing. What that tells me is that line 25 in easypost_shipping.php is being called while I’m writing this blog post. Huh? Yeah, what’s happening is that the EasyShipper developer tied the set_customs_value() function call with the ‘save_post’ action. In other words, every time someone saves a $post type object in WordPress this code will execute. The reason is because WooCommerce, which is the plugin that we use for our ecommerce functionality, leverages the WordPress $post framework to create and manage orders. Pretty clever actually but can have these conflicts where a entry that’s expected to be a Product is actually a Post. I fixed the issue by checking if wc_customs_value field exists in the $_POST before trying to read it:
if( array_key_exists('wc_customs_value',$_POST) ){ // line 25 in easypost_shipping.php with fix
Using Cyberduck and Debug Console
I use a Mac for development so in order to edit files on the Flomio server, I installed Cyberduck. Once configured to access your server, it provides a familiar file navigation UI with native editor support. I can open files in the Textmate editor, make changes, and save them directly to the server. This makes developing straight on the live production server more feasible.
Despite this convenient setup, it’s far from ideal. If you’re making lots of changes to the code and still learning PHP syntax, it can become very time consuming at several seconds per save and server sync. To speed things up you can use the Debug bar and Debug Console plugins. With WP_DEBUG set to true, these plugins show you a live debug.log feed and PHP execution environment right within the browser. It looks something like this:
The Debug bar provides a split screen view so you can still see your WordPress admin content. In the example I’m pulling out the metadata from order #6133 and looking through the available fields. I used this experiment to get the syntax right for pulling out the _custom_tracking_link data and protecting against it being empty. Once I got it working right I was able to add this code to the order complete email template so that tracking information is included once packages are shipped.
Server-side Search
The debug bar and console are pretty helpful, but when I need to really get my hands dirty I SSH straight to the server. I can navigate around using terminal commands and editing files with vi. With practice, this can be quite effective to get things done quickly. The most powerful feature is being able to search the entire site code base for stuff any text very quickly. For instance, in all the cleanup I was doing I left an extra “:” in one of the files I edited. This was causing pages to render it. Finding where it was introduced was surprisingly difficult but I finally tracked it down with this command:
find . -type f -regex ".*\.php" -mtime -3 -print0 | xargs -0 grep -nsHR ":"
This find command recursively searches the current directory down through every subdirectory and file with the “php” extension that was update less than 3 days ago. The output file list is then passed through the grep command to source out the occurrences of “:” in these files. Checking through the results list, I methodically inserted the following wp_die() function throughout different files to break execution in key places until I found the pesky little bug:
wp_die("Richard broke it!");
There you have it. That’s how I go about troubleshooting our WordPress site and hopefully it helps some folks avoid getting stuck. With these tools I’m constantly learning the vast capabilities of WordPress and I’m looking forward to offering direct integration to our software products, NFC Kiosk and NFC Actions, going forward.
WooCommerce EasyPost Shipping Method
After all the work repairing/improving the EasyShipper code, I decided to formalize the effort into a plugin of our own. The WooCommerce EasyPost Shipping Method plugin offers several improvements over EasyShipper including:
- Support for purchasing shipping labels at the point of order fulfillment
- Support for international shipping (ie customs forms management and printing)
- Support for different print layouts (ie saves on time, paper, customizing)
- Works alongside the Print Invoices/Packing List plugin for quick fulfillment of orders!!
- Documentation and refactored WC_EasyPost class for further feature creep
- Fixed shipping method persistence issue from the WC Cart process
- Defaults to USPS Priority FlatRate Envelope a standard shipping option
Check out this screencast video I put together so you can see how the plugin integrates well with the WooCommerce admin workflow. In concert with the Print Invoice/Package List plugin, the solution offers a great order fulfillment process for small to medium sized web stores. We easily handle 100 shipments a week using this setup. It’s a cheaper and more effective option than anything we tried in the past, including Shipstation, Endicia, Stamps.com, and USPS Click-n-Ship.
Leave a Reply
Want to join the discussion?Feel free to contribute!