This introduction to PHP output buffering and its uses in WordPress contains a few helpful resources:
- A first code demo that shows how PHP output buffering is helpful for WordPress shortcodes.
- A second code demo that shows how PHP output buffering can help create complex
the_content
filters that use readable HTML output. - A simple child theme (available on GitHub) that contains both these code demos and lets you play with the code yourself.
Enjoy this detailed introduction to PHP output buffering for WordPress!
When I was learning PHP, one of the first things that really stumped me was the difference between code that created output—”stuff,” content visible as HTML to the user?and code that didn’t.
What I now understand is that most PHP code will transform data, but it won’t show it to users. PHP echo
statements are essentially output generators: they “leak out” of PHP code, creating meaningful, visible output, while most other PHP code doesn’t.
There’s a very powerful exception to the rules I just described: PHP output buffering. With output buffering, you can actually capture, store, and modify echo
ed output—before it actually outputs. This process of capturing and working with echo
ed output is what “output buffering” means. It’s a topic that first confused me, and then (after, I suppose, a… buffer) blew my mind.
Serious About Learning WordPress Development?
Get Up and Running Today
Up and Running is our complete “learn WordPress development” course. Now in its updated and expanded Third Edition, it’s helped hundreds of happy buyers learn WordPress development the fast, smart, and thorough way.Here’s what they have to say:
“I think anyone interested in learning WordPress development NEEDS this course. Watching the videos was like a bunch of lights being turned on.” -Jason, WordPress developer
“Other courses I’ve tried nearly always lack clear explanations for why WordPress does things a certain way, or how things work together. Up and Running does all of this, and everything is explained clearly and in easy-to-understand language.” -Caroline, WordPress freelancer
So let’s get to unlocking the power of PHP output buffering, and its many uses in WordPress. In this article we’ll:
- Understand the difference between output and data-processing in a bit more detail
- Explain the basics of PHP output buffering
- Get to the heart of why PHP output buffering can be such a vital technique for complex WordPress shortcodes
- Explore another use of output buffering in WordPress: HTML-heavy uses of the
the_content
filter - Touch on the possibility of using them for widgets
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 withget_the
.
PHP consists of two kinds of operations:
- Trying to show things, and
- Trying to do data manipulation.
The most immediate way that people learning WordPress understand this difference is oftten through the difference between WordPress template tags that start with the word the
, like the_title()
and those that start with get_the
, like get_the_title()
. That was true for me.
Let’s get concrete with a simple, 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.
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(); // Outputs 1
get_the_ID(); // No output
echo get_the_ID(); // Outputs 1
(the_ID() + 20); // Outputs 1 (think carefully about why!)
echo (get_the_ID() + 20); // Outputs 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()
. $id = the_ID()
, while it looks quite similar, will really confuse you, because you’ll have a value that isn’t really set.
I remember struggling with this concept for literal hours (maybe even days). The crucial thing is that data that you manipulate exists in PHP Land, 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. That’s why the line the_ID() + 20
above outputs 1. Because the the_ID()
call in WordPress contains an echo
without a return
. So our line has nothing on which to do its operation. Instead we simply have the 1
result from the the_ID()
call being echoed on the screen.
All these rules are pretty firm in PHP, except for (drumroll please): output buffering.
PHP’s Output Buffering API
With PHP output buffering running: rather than just showing the data being
echo
ed or otherwise displayed, PHP will catch it for you and let you save it out to a variable.
Let’s say you 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. The output buffer is the holder into which PHP will store what would otherwise be shown, in a way that you can work with it in your code.
When you have an output buffer running, rather than just showing the data being echo
ed and 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. This is a powerful concept to let you change the impact of code that is simpler.
The basics of PHP’s output buffering are a suite of functions that start ob_
, which is an abbreviation of the term “output buffer.”
ob_start()
: Start Buffering Output
You’ll start your output buffer with a call to a well-named function: ob_start()
.
ob_start()
turns on the buffer, and socks away everything that would otherwise hit the web browser into a string. It’s your way of saying, “Until I turn this buffer off, everything that would’ve been outputted, even echo
ed content, instead gets stored as a progressively longer single string in the buffer.”
So Many ob_
Functions
Once you’ve started your buffer with ob_start()
and have entered some buffered output, there are a few steps to harvesting that output and resetting the buffer.
The step-by-step version is that you’d retrieve the contents of the buffer with ob_get_contents()
, which gives you the buffered output to either save as a PHP variable or just echo
directly..
But ob_get_contents()
leaves the existing contents in the output buffer, and also keeps it running. So you’d also need to run ob_clean()
to clear out the buffer, and ob_end_clean()
when you’re really done with it. PHP.net’s documentation of Output Buffering, like most other language features, is pretty friendly and accessible, so if you want to know the step-by-step approach I’d recommend that as your source.
Fortunately, there’s a single function that “harvests” and deactivates your buffer all at once: ob_get_clean()
.
ob_get_clean()
: Three Birds, One Stone
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 mention the need to both clean and turn off your output buffer for the purpose of pointing out a PHP function that does both things for you: ob_get_clean()
. In fact, ob_get_clean()
does a total of three things together:
- Fetch the contents of the buffer,
- Clean out the buffer, and
- Turn off further buffering. (This isn’t shown in the function name, unfortunately, but it does do it.)
Probably 90% of times I use PHP’s output buffer, I just retrieve its contents with a call to ob_get_clean()
.
So for our simple code demo, let’s use ob_start()
and ob_get_clean()
to change our ID (pretending we’re in a world where get_the_ID()
doesn’t exist). Here’s how it looks:
ob_start();
the_ID();
$id = ob_get_clean();
echo $id + 20;
One thing worth noting here: we always get a string
type value from ob_get_clean
(or ob_get_contents
). Because PHP is loosely typed, it’ll happily make that string '1'
into a number and add 20 to it for us here. However, you’ll still need to keep track of these kinds of type conversions in PHP, as they can lead to unexpected results.
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_example_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_example_shortcode] can be as simple as:
add_shortcode(
'our_example_shortcode',
'wpshout_example_shortcode_function'
);
function wpshout_example_shortcode_function() {
return 'I show up where you called the 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.
Shortcodes Don’t echo
, they return
What’s very important to realize about shortcodes is the following: you want to return
what should be shown, not echo
it.
When you mistakenly echo
something in a shortcode function, it just appears right at the top of your post content, where the_content()
is called in your theme, rather than replacing what it should have in the correct position in the post. Shortcodes always have to return
text content to appear in the correct place.
Because we 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—then we’ve got two bad options:
- Put all your HTML inside PHP strings, playing all the dances with quotes. (You know,
'<img src="'.get_the_ID().'">'
sort of fun…) include
a template file full of your HTML & PHP, but have it appear in the wrong place.
This is where PHP output buffering becomes a lifesaver, and why I love output buffering for shortcodes specifically. It lets you use real HTML templates with immense ease, without having to worry about going against how shortcodes work. The following demo shows how.
Demo 1: Why PHP Output Buffering is Super-Helpful for Shortcodes
This demo gives a realistic scenario in which PHP output buffering will be very helpful for shortcodes.
View the Full Source Yourself
I’ve created a simple Twenty Seventeen child theme that contains the full code for both demos below. Please check it out on GitHub! You can download it as a ZIP, or browse the source.
The Goal: Output a Complex Template in a Shortcode
Our goal in this demo is to create a shortcode that can output a relatively complex HTML/PHP template. This template is in its own file, post-quickview.php
, in a subfolder in our theme, custom-templates
:
// Environment: This is the post-quickview.php file inside the custom-templates folder.
<div class="post-quickview">
<h1 class="quickview-title"><?php the_title(); ?></h1>
<div class="quickview-featured-image"><?php the_post_thumbnail( 'large' ); ?></div>
<?php the_excerpt(); ?>
</div>
If we output it properly, we get a little “quickview” of post title, featured image, and excerpt, as follows:
Now, here’s the kicker: we want to be able to serve that template as a shortcode, so that we can put our little “quickview” previews anywhere in our post content. So we should be able to just choose a post by its ID, as follows:
And get the following result on the front end:
Clear enough? Here’s the code to do it, with a very crucial use of PHP output buffering to keep get_template_part()
from its default behavior, which is to “leak” (echo
) right onto the page:
add_shortcode( 'wpshout_quickview_post', 'wpshout_quickview_post' );
function wpshout_quickview_post( $atts ) {
// If we didn't choose a post ID, return
if( ! $atts || ! $atts['post_id'] ) {
return 'No post ID specified.';
}
// Fetch current post object and set the global $post to point to it
$this_post = get_post( $atts['post_id'] );
global $post;
$post = $this_post;
setup_postdata( $post );
// Start output buffering so get_template_part doesn't output to the page
ob_start();
// Get template file output
get_template_part( 'custom-templates/post-quickview' );
// Save output and stop output buffering
$output = ob_get_clean();
// Return $post to its original state
wp_reset_postdata();
// Return buffered output to be output in shortcode location
return $output;
}
Cool, right? Our post-quickview.php
template itself can be written in raw HTML, and is free to use all sorts of PHP functions that generate output, like the_title()
and the_excerpt()
—and we can still include it into a shortcode that return
s HTML content rather than echo
ing it.
Here’s another benefit of this example: we can keep the actual PHP code for our shortcode completely free of HTML. Everything that does actually print onto the screen is in one place: post-quickview.php
. It’s not cobbled together in the shortcode function itself and potentially a bunch of other places. This sort of purity and clear separation of concerns isn’t super common in WordPress code, but it’s helpful and a very good practice.
Demo 2: Output Buffering in a the_content
Filter Function
When else in WordPress do we want to return
rather than echo
? How about in WordPress filter functions?
This second demo adds a rather lengthy HTML footer to the bottom of single Posts by hooking into the the_content
filter. Now, a WordPress filter shouldn’t usually be echo
ing stuff on its own, but rather modifying something (here, a string) it’s given and then return
ing it back. So how are we going to build our HTML string without echoing it?
Here’s the grim way:
$string = '<hr />
<div class="single-footer">
<h3>Footer section</h2>
...
';
return $string;
But we’ve got a better one! We’ll just write raw HTML into the function directly, and use output buffering to “catch” that HTML so that we can return
it rather than outputting it:
// PHP output buffering for the WordPress the_content filter hook
add_filter( 'the_content', 'wpshout_add_single_post_footer' );
function wpshout_add_single_post_footer( $content ) {
// Only on single Posts
if( ! is_singular( 'post' ) ) {
return $content;
}
// Start output buffering so we can "write" to the page
ob_start(); ?>
<hr />
<div class="single-footer">
<h3>Footer section</h2>
<p>I can do all kinds of HTML here</p>
<table>
<tr>
<td>How about a table?</td>
<td>That seems</td>
<td>Easy enough</td>
</tr>
</table>
</div>
<?php
// Get our output string and save to a variable
$footer = ob_get_clean();
// Return the string appended to the content
return $content . $footer;
}
Here’s what this looks like put into effect on a demo site:
For the cleanest possible code, as we noted in Demo #1, it would be very easy to break this HTML content out into a template file of its own and include it with get_template_part()
—again, because of the power of output buffering to stop get_template_part()
from outputting directly to the page.
Consider: Output Buffer for Templating in Widgets
In addition to shortcodes, another place in WordPress where I might find myself reaching for PHP output buffering is the creation of widgets. Unlike shortcodes, the widget
method of you WP_Widget
extending class doesn’t need to return
the desired output, it can just echo
it. But like shortcodes, I still dislike mixing my HTML with my straight PHP code. So that’s where I might use output buffering.
If you’re not really familiar with creating widgets in WordPress PHP, you’ll want to check out our free course on it:
I’ll be assuming you understand the general shape of WordPress widgets in the rest of this section, so if you want it to make sense and you don’t already know, pause here and go read it.
As I was saying, because I don’t really like mixing really logic-oriented PHP code with output-oriented PHP code, I’ll often template in my widgets, just as with shortcodes. The difference is simply that the relevant methods of a widget will show their output. So the code looks remarkably similar, with the only real change being that return
becomes an echo
.
function widget() {
ob_start();
include 'path/to/your/template.php';
echo ob_get_clean();
}
In widgets, however, this code isn’t as clearly the right choice. After all, we started this article by explaining that if you can echo
things, you’ll not really need to use PHP’s output buffer. And indeed, I’ll often simply write the code as:
function widget() {
include 'path/to/your/template.php';
}
The primary reason that I may use the output buffer is the case where there’s some need to manipulate the widget (or form) output in a complex way. That’s rare thought. With both shortcodes and widgets, output buffering is one of the most useful and modestly esoteric features of PHP which make your WordPress code way better. But with widgets, the need for using output buffering for templating is much less absolute than it is in shortcodes.
PHP Output Buffering: A Very Useful Tool
We’ve just covered a simple place where I think WordPress developers can get huge benefits from output buffering—shortcodes—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 codebase. 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. But you don’t need to use it all the time, as WordPress shortcodes illustrate. 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 PHP for WordPress.
By the way: if you like our style of explaining WordPress’s PHP backbone, there’s an awful lot more where that came from in our complete “learn WordPress development” guide, Up and Running. Have a look! Real clarity in WordPress development starts at under $100.
Happy hacking!
Well being a learner of PHP, its going to save a lot of time.
Thanks for writing about it David. Cheers!
Thanks for saving my bacon last night! Thanks, David!
It’s awesome how we can keep highlighting on HTML and produce faster using OB. Great article indeed!
Thanks David,
I was developing a shortcode in a plugin that returns a form, and I wanted to use wp_editor on one of the textareas. Since wp_editor echos it’s output (i.e. it does not return it), the editor appeared at the top of the page and the HTML generated was outside the form. So output buffering of wp-editor is exactly what is needed. I didn’t know it was this easy to do until I found your article. Perfect!
[…] Understanding PHP Output Buffering, and Why It’s Great for Shortcodes | WPShout – Good basic understanding of using output buffering in WordPress. […]
[…] Source: Understanding PHP Output Buffering, and Why It’s Great for Shortcodes | WPShout […]
This is awesome! I was struggling to get my shortcode (that did a custom loop) to output at the right place. You explained everything very clearly and ended up adding the output buffer and voila. Thank you!
Thanks a lot, Bowe! 🙂
[…] If you need to know more about writing WordPress shortcodes, see here for a general introduction. If you’d like to know more about our use of the ob_start() and ob_get_clean() functions, check David’s excellent tutorial on output buffering for shortcodes. […]
Hello, you me gave a idea 🙂
As it might supposed, get_template_part() should return a value (actually not 🙁
Then with buffering we can hook this value 🙂
ob_start();
get_template_part( ‘template-parts/loop’, ‘index’ );
$tpl = apply_filters(‘the_tpl’, ob_get_clean());
echo $tpl;
and in your plugin or functions.php:
add_filter( ‘the_tpl’, function( $tpl ) {
// treatments
//
return $tpl;
} );
[…] Enfin, impossible.. c’est ce que je croyais jusqu’à il y a quelques jours… lorsque j’ai lu un article à propos de la “bufferisation” avec PHP : “Understanding PHP Output Buffering, and Why It’s Great for Shortcodes“. […]
In most of the cases that developers using output buffering in themes or plugins, I see huge problems with cache and while using hooks. How do you solve this?
I’m thinking that David’s example buffers rather little: a few lines at a time, and then PHP moves on.
On the other hand, you can (mis?)use output buffering to buffer the whole HTML document you’re building for one reason or another, and that can have really serious performance problems.
Does that distinction make sense?
Thank you for this useful article. It’s nice to see programmers that remember how it was in the days they were learning and explain it to those who are learning just now.