Quantcast
Channel: Back-End Development - WPShout
Viewing all articles
Browse latest Browse all 159

Understanding PHP Output Buffering, and Why It’s Great for Shortcodes

$
0
0

One of the first things in PHP that really stumped me was the difference between code that created output and code that didn’t. I knew, vaguely, that things that had an echo statement in PHP meant something important, but that was about it.

What I now get, is that echo statements are essentially output generators: they “leak out” of other PHP code. They create meaningful, visible output, most other PHP code doesn’t. Most other PHP code will transform data, but it won’t show it to users. But what we’re focusing on here is that you can actually capture, store, and use echoed output in a way that initially confused me and then blew my mind a bit.

So let’s get to it. Basically, we’ll:

  1. Understand the difference between output and data-processing in a bit more detail
  2. Explain the basics of output buffering in PHP
  3. And get to the heart of why I find this such a vital technique for complex WordPress shortcodes

The Difference Between Programming and Output in PHP

The difference between trying to show things and trying to do data manipulation is the difference between WordPress template tags that start with the word the and those that start with get_the.

There’s two types of things in PHP: trying to show things and trying to do data manipulation. The way most people learning WordPress come to terms with this difference is through the difference between WordPress template tags that start with the word the and those that start with get_the. That was true for me.

To get concrete (with a simple, and unlikely, example), lets pretend that in a theme we want to show the numeric ID of a post, but we want to add 20 to it first. (Why, other than masochism? I don’t know, but it’s the simplest example that captures all useful concepts.)

This code, assuming the ID of the post in question in 1, would have the effect of showing the values listed by the comments below the statements:

the_ID(); 
// 1
get_the_ID(); 
// [no output]
echo get_the_ID(); 
// 1
(the_ID() + 20);
// 1 [(!?)]
echo (get_the_ID() + 20);
// 21

get_the_ID is a function that returns a value to you, to further process or just hold onto. Conversely, the_ID() only shows the value, it doesn’t hand it, or anything, back to you.

Basically, what I’m getting at is that data — strings, numbers, whatever — that exist in PHP Land aren’t shown by default. get_the_ID is a function that returns a value to you, to further process or just hold onto. Conversely, the_ID() only shows the value, it doesn’t hand it, or anything, back to you. So if you wanted to save a value of the ID to a variable, you’d want to write a statement like $id = get_the_ID().

This is one of those things that today I can quickly gloss over like it’s trivial. But I remember struggling with this concept for literal hours (maybe even days). The crucial thing is that data that you manipulate exists in PHP, but if you don’t echo it — either with something like echo get_the_ID(), or with the the_ID function (which basically does the previous statement under the hood) — it won’t show up. Conversely, if you echo something, that doesn’t create something you can easily manipulate in PHP. Well, except for this “output buffering” thing…

PHP’s Output Buffering API

With output buffering running: rather than just showing the data being echoed or otherwise displayed, PHP will catch it for you and let you save it out to a variable.

Let’s say you need or want to manipulate the value that comes out of the the_ID() and we’re in some alternate world where WordPress doesn’t have a get_the_ID() function. What do you do? Well for just this sort of scenario, PHP has the concept of an output buffer that a user can manipulate.

Basically, when you have an output buffer running, rather than just showing the data being echoed or otherwise displayed, PHP will catch it for you and let you save it out to a variable. Then, after you’ve made your changes to it (or not), you can echo it yourself.

start-stop-buttonsThe basics of PHP’s output buffering are a suite of functions that start ob_, which (as you probably guessed) is an abbreviation of the term “output buffer.” So you start the output buffer with a call to ob_start(). This turns on the buffer, and basically socks away everything that would otherwise hit the web browser in a string.

You then retrieve the contents of that buffer with a function like ob_get_contents(). That lets you either just echo the value directly, or store it as a variable. Then you’re able to actually operate upon that string of buffered content.

It’s worth knowing, as you use output buffering, that ob_get_contents() leaves the existing contents in the output buffer, and also keeps it running. So if you want to be a good citizen, you’ll probably want to do an ob_clean() after you get the contents of the buffer, and an ob_end_clean() when you’re really done with it. But further details on those, are other ob_ functions is outside of our scope. Thankfully, PHP.net’s documentation of Output Buffering, like most other language features, is pretty friendly and accessible.

90% of the times I use PHP’s output buffer, I actually just retrieve the contents of it with a call to ob_get_clean() which does three things together: fetch the contents of the buffer, clean out the buffer, and turn off further buffering.

I just mention the idea of cleaning and turning off your output buffer, because for 90% of the times I use PHP’s output buffer, I actually just retrieve the contents of it with a call to ob_get_clean() which does three things together: fetch the contents of the buffer, clean out the buffer, and turn off further buffering.

So, code time. To accomplish the goal we had above in a world without get_the_ID(), we could do this:

ob_start();
the_ID();
$id = ob_get_clean();
echo $id + 20;

One slightly academic thing worth noting here: we always get a string type value from ob_get_clean (or ob_get_contents). Because PHP is loosely typed and therefore doesn’t typically make a noise about this sort of thing, it’ll happily make that string '1' into a number and add 20 to it for us here. But such type-conversions PHP will do for you can behave different than you’d expect, so it’s worth knowing that this code is doing that.

A Quick Refresher on WordPress Shortcodes

So if you know about WordPress shortcodes, you know they’re a simple way to add some programming into the body of a post. By just inserting something like [our_fake_shortcode] into the body of our post, we can replace that with some output from a function. It’s so beautiful and useful. The code to replace [our_fake_shortcode] can be as simple as:

add_shortcode(
    'our_fake_shortcode',
    'wpshout_fake_shortcode_function'
);
function wpshout_fake_shortcode_function() {
    return 'REPLACED THAT SHORTCODE!!';
}

Basically, just call add_shortcode (which is a bit like a really special case of add_filter or add_action) with the name of your shortcode and the name of your function and you’re set.

What’s important to realize about shortcodes, though, is that you want to return what should be shown, not echo it. If you’ve never seen it, when you echo something in a shortcode function, it just appears right at the top of where the_content() is called in your theme, rather than in its place, replacing what it should have.

Why Output Buffering Makes Shortcodes Better

So, because of this need to return our content for shortcode, if we want to generate a lot of raw HTML in our shortcode — say to draw complex tables, or similar — we’ve got two bad options:Dances with Wolves cover

  1. Put all your HTML inside PHP strings, playing all the dances with quotes. (You know, '<img src="'.get_the_ID().'">' sort of fun…)
  2. include a template file full of your HTML & PHP, but have it appear in the wrong place.

You may have beat me to the punchline, but this is why I love output buffering with shortcodes. You get the ability to use real templates with immense ease, and you also get to have your result appear in the right place.

Just to make it quite concrete, here’s a tweaked version of our function:

function wpshout_fake_shortcode_function() {
    ob_start();
    echo 'REPLACED THAT SHORTCODE!!';
    include 'path/to/your/template.php';
    return ob_get_clean();
}

And a trivial example of our template.php

<p class="fake-template-class">This post was titled: <?php the_title(); ?></p>
<?php custom_html_drawing_function(); ?>

And just like that, we’re able to segegate our template on its own, but have it appear as we’d expect from our shortcode! What’s not to love!?

PHP’s Output Buffer: A Very Useful Tool

We’ve just covered a simple place where I think WordPress developers can get huge benefits from output buffering, but it doesn’t end there. Output buffering is one of the most valuable ways you can make your life easier inside of any sloppy legacy PHP codebases. An example I have too much experience with: you’ve got a massive and frightening function that both does some useful action AND spits out some output you don’t want? Turn on that output buffer, call your function (and get its result), and throw away the buffer.

It’s also just really fun and useful in many other places. As we’ve shown, it’s really useful with WordPress shortcodes. Armed with a solid understanding of what things produce output and how to use the output buffer, you’re well on your way to mastering WordPress. Happy hacking!


Viewing all articles
Browse latest Browse all 159

Trending Articles