I got a call from a new client last week. Their WooCommerce site was throwing errors on the order confirmation page, but only sometimes. The previous developer was long gone, of course. The client was frustrated and losing money on abandoned carts because customers were getting spooked by the error messages. Total mess.
After about ten minutes of digging, I found the culprit: a custom function that built a dynamic “thank you” message, and it was a perfect example of bad PHP string formatting. It was a massive chain of concatenated strings and variables, a dozen lines long, and so fragile that if a customer had no last name entered, the whole thing broke.
The “easy” fix that isn’t
My first thought, and what a lot of devs would do, is to just tidy it up a bit. Maybe switch to double quotes and variable expansion to make it shorter. That’s a band-aid on a broken leg. It looks a little better, but the underlying problem is still there: the logic is messy, it’s hard to read, and it’s a nightmare the day you need to translate the site. For reference, the original code looked something like this:
$message = '<p>Hey ' . $order->get_billing_first_name() . '! Thanks for your order of ' . $order->get_item_count() . ' items. We'll get it shipped out by ' . $shipping_date . '.</p>';You can see the problem. One misplaced dot or quote and the whole thing falls apart. My first “fix” with double quotes was better, but it still wasn’t the right way to handle this.
A better approach to PHP string formatting
The maintainable solution is to use a proper formatting function. My go-to, and what WordPress core uses all over the place, is sprintf. It separates the template of your string from the data you drop into it, which makes the code easy to read and debug. It also makes life much easier for translation plugins, which tend to struggle with concatenated strings.
And it’s not even hard. You replace your variables with placeholders like %s for a string or %d for a number, then pass the variables to the function in that same order. The idea has been around for ages, and there’s a good write-up on it over at carlalexander.ca.
$template = '<p>Hey %s! Thanks for your order of %d items. We'll get it shipped out by %s.</p>';
$message = sprintf(
$template,
$order->get_billing_first_name(),
$order->get_item_count(),
$shipping_date
);So, what’s the point?
This might seem like a small thing, but it’s the gap between amateur code and professional code. Writing clean, readable code isn’t about showing off. It saves you, and your client, a headache six months from now. When you’re debugging at 2 AM, you’ll be glad you took the extra minute to do it right.
- It’s readable. You can see the shape of the output at a glance instead of getting lost in a sea of dots and quotes.
- It’s easy to maintain. Need to change the wording? Edit the template string, not the logic.
- It plays well with translation. Translation tools understand
sprintfformats, so internationalization hurts a lot less.
This stuff gets complicated fast. If you’re tired of debugging someone else’s mess and just want your site to work, drop my team a line. We’ve probably seen it before.