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

When I was learning PHP, one of the first things 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. This is called “output buffering” and it initially confused me and then blew my mind.

So let’s get to unlocking the power of PHP output buffering. In this article we’ll:

  1. Understand the difference between output and data-processing in a bit more detail
  2. Explain the basics of PHP output buffering
  3. Get to the heart of why I find this such a vital technique for complex WordPress shortcodes
  4. And 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 with get_the.

There’s two types of operations you’ll do 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:

// 1
// [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(). $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 of these rules are pretty firm in PHP, except for this “output buffering” thing…

PHP’s Output Buffering API

With PHP 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 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 echoed 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.

PHP output buffering is important for creating shortcodesThe 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. (The last operation isn’t shown in the function name, unfortunately, but it does it.)

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

$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 it 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:

function wpshout_fake_shortcode_function() {

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 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.

Why Output Buffering Makes Shortcodes Better

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() {
    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 segregate our template on its own, but have it appear as we’d expect from our shortcode! What’s not to love!? This allows up to have a file at path/to/your/template.php which is just HTML with some PHP output mixed in, and we can keep our actual PHP code for our shortcode completely free of HTML. Purity in this way isn’t super common in WordPress code, but it’s helpful and a very good practice.

By the way, if you want to get deeper into the weeds of WordPress development then check out our course to help you learn WordPress development.

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:

Creating WordPress Widgets: The Complete Guide

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() {
    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. Happy hacking!

Image credit: https://www.flickr.com/photos/ell-r-brown/4226124148/, Kevin Gessner

12 Responses


  • MirceaBurdusa says:

    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.

  • 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?

    • fredclaymeyer says:

      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?

  • lipaonline says:

    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 :)


    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;

    } );

  • Bowe Frankema says:

    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!

  • Christer Fernstrom says:

    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!

  • Eric Gruby says:

    It’s awesome how we can keep highlighting on HTML and produce faster using OB. Great article indeed!


Add a comment