Up Periscope: Practical Uses of print_r() in WordPress Development

By default, you can’t look directly at PHP processing, only at its effects.

A persistent need in programming is to know exactly what’s going on with your code. This can be especially tricky in WordPress, for at least three reasons:

  1. WordPress’s PHP code can be altered extensively in numerous places: in parent themes, child themes, and plugins.
  2. WordPress’s PHP code contains a great deal of global state: invisible statuses, such as the identity of the current post, that can affect your own code in ways that are difficult to predict.
  3. PHP code always fully executes before it’s viewable in-browser as HTML.

This third point means that, by default, you can’t look directly at PHP processing, only at its effects. This is different from, say, JavaScript, whose console.log functionality allows you to “think with” JavaScript as it executes in your browser.

It’s also different from plain HTML and CSS, where what shows up in your browser is the markup (the “code”) itself, and can be transparently accessed and analyzed with tools like Chrome’s Developer Tools.

So today, I’m going to introduce the closest thing in PHP to console.log: the print_r() function. I’ll explain print_r() and under what circumstances you can use it (not on live sites, please!), then present a couple of practical use cases in WordPress development.

What print_r() Is and Why It’s Helpful

print_r() prints information about a variable into HTML, so you can learn about that variable in your web browser.

According to PHP’s official function reference, print_r() “prints human-readable information about a variable.” What that means is that it prints the values that a variable takes into HTML, so you can learn all about that variable directly in your web browser.

Here’s an example, straight from php.net:

$a = array( 'a' => 'apple', 'b' => 'banana', 'c' => array( 'x', 'y', 'z' ) );
print_r( $a );

If you run this code, the print_r() command will print into your browser the following:

Array
(
    [a] => apple
    [b] => banana
    [c] => Array
        (
            [0] => x
            [1] => y
            [2] => z
        )
)

If you run the code above right before the post’s content—by hooking into the_content, as we’ll discuss below—you see the following (in-browser on the left, in Chrome’s Developer Tools on the right):

print_r demo in browser

Click to enlarge

Why is this cool? Because it lets you introspect into—understand everything about—the variables you’re working with as you do PHP development.

In other words, when you call, say, global $post; to work with the current $post object, you don’t just have to hope you understand what $post has in it: you can actually check. You’ll start to see the power of this in the examples below.

Not for Live Sites

As print_r() spits ugly markup onto the page, running it on live sites is not advised.

print_r() is for debugging, and the best place to debug things is in a staging environment. As print_r() spits ugly markup onto the page, running it on live sites is not advised—although possible if you don’t have alternatives.

If you do need to run a var_dump() on a live site, you can do it slightly more responsibly by enclosing the results in a hidden div:

<div style="display: none;"><?php var_dump( $testvar ); ?></div>

You can then view the page source (using your browser’s “View Page Source” feature or its development tools feature set) to see the results of the var_dump() without impacting live users.

print_r(), var_dump(), and echo

I don’t use print_r() exclusively to inspect variables: two other methods, var_dump() and echo, can work similarly.

echo, the main PHP function that prints things out to the page, can be used to inspect variables. However, it only works on strings and things that can be easily cast to strings, like integers. If you try to echo an array, you get just Array, and if you echo an object, you crash the site with a fatal error—neither very helpful for our “figure out what’s going on” purposes.

I do use var_dump() fairly often. var_dump() is more thorough than print_r(), but this means that it’s less readable, as in the following comparison:

php print_r example

print_r of a WP_Query object

var-dump of the same WP_Query object

var-dump of the same WP_Query object

However, sometimes you need var_dump() to fill in information that print_r() won’t show you, as in this example from Stack Overflow:

// Given $testarr = array( '', false, 42, array( '42' ) );

// Running var_dump( $testarr ); gives this result:
array(4) {
  [0]=> string(0) ""
  [1]=> bool(false)
  [2]=> int(42)
  [3]=> array(1) {[0]=>string(2) "42")}
}

// Running print_r( $testarr ); gives this result:
Array (
    [0] =>
    [1] =>
    [2] => 42
    [3] => Array ([0] => 42)
)

As you can see, print_r() won’t distinguish between integers (42) and numerical strings ("42"), or between empty strings ("") and the boolean false. These distinctions matter, so reach for var_dump() when you need it!

For our purposes, though, print_r() is easier to read quickly, and it’s usually good enough to learn what we need to know about the variables we’re working with.

Example 1: Displaying All of a Post’s Custom Fields and their Values

For our first print_r() demo, we’re going to inspect all of a post’s custom fields, also called its post meta. I had to do this exact inspection recently because I wasn’t sure what custom fields some of my post types were carrying.

In a staging (not live) environment, in a new plugin or in your theme’s functions.php, the code we’ll write looks like this:

add_filter( 'the_content', 'wpshout_print_r_demo' );
function wpshout_print_r_demo( $content ) {
	$meta = get_post_meta( get_the_ID() );
	print_r( $meta );
	return $content;
}

The code works as follows:

  1. We first hook into the the_content WordPress filter. We’re going to run our custom function wpshout_print_r_demo(), and we’re given the current post’s content, $content, to play with.
  2. get_post_meta() retrieves all custom fields for a given post ID, which we supply for the current post using get_the_ID(). We save all the fetched metadata to a variable, $meta.
  3. Next, we print_r() $meta, putting it onto the page in a human-readable form.
  4. Finally, we return the post’s content, $content, unchanged.

Why are we hooking this onto the the_content filter? For two reasons: first, hooking into the_content lets us use in-the-Loop functions like get_the_ID(). Second, it lets us know exactly where our print_r is going to print out: right above the content itself.

Here’s the result, viewed in-browser on the left and in Chrome Developer Tools on the right:

Click to enlarge

Click to enlarge

As you can see, we get an at-a-glance look at all the post meta attached to the current post—and as we browse the site, we’ll see this information for each post we look at until we disable the code above.

Example 2: Displaying the Posts Fetched by a Custom WP_Query

In this second print_r() demo, we’re going to display the posts fetched by a custom WP_Query. I run code similar to this frequently to quickly verify that my custom WP_Querys are behaving as I expect.

Here’s the code:

add_filter( 'the_content', 'wpshout_print_r_demo' );
function wpshout_print_r_demo( $content ) {
	$args = array(
		'post_type' => 'post',
		'tax_query' => array(
			array(
				'taxonomy' => 'category',
				'field'    => 'slug',
				'terms'    => 'ideas',
			),
		),
		'orderby' => 'title',
		'order' => 'DESC',
	);
	$newquery = new WP_Query( $args );
	print_r( $newquery->posts );
	return $content;
}

As before, we’re hooking into the_content for convenience.

This time, we’re writing a custom query that fetches the following posts:

  1. Posts whose post_type is post,
  2. In the “Ideas” category (whose slug is ideas),
  3. Ordered in reverse alphabetical order.

We do this by creating an $args variable that specifies the three parameters just listed. We then pass $args into our WP_Query constructor, and the resulting WP_Query object gets saved to the variable $newquery. (If you’re not familiar with writing custom queries in WordPress, please check out our guide on the subject.)

Now for our print_r(): we’re going to print $newquery->posts. This means that we want just the posts property of the fetched WP_Query object—not the whole object itself.

So what we get on the page is a list of fetched post objects, with all their properties:

print_r wp_query example

Click to enlarge

As you can see, there’s a ton of data here; but scanning and seeing that each of the fetched posts is indeed from our “Ideas” category, and searching the page for post_title (and seeing that it does indeed work in reverse alphabetical order), provides enough of a commonsense check that I’ve written my query properly.

Thanks for Reading!

This has been an introduction to a very important element of my day-to-day WordPress development: print_r() and the power to actually understand what’s in a given variable. Thanks for reading, and we’d love to hear your comments and questions below!

Image credit: Ian Muttoo


7 Responses

Comments

  • justin maurer says:

    Might be worth mentioning that you can print pre tags to make things even MORE readable.


    echo '';
    print_r($a);
    echo '';

    Or, to go one step further, create a helper function, like this guy , so you can still run a simple function each time.

  • lkraav says:

    Just use Kint instead. Last thing you want to worry about during a debugging run is formatting, display and usability of debug data.

    https://wordpress.org/plugins/pco-kint/

    Put `d( $some_variable )` in your code and never look back.

    Yes, `print_r()` is still relevant when `error_log()` is your only option to see data (AJAX, etc).

  • andykillen says:

    perhaps mentioning

    error_log(print_r($array, true));

    would have been more useful still as it would not be removed from the screen on every refresh. In fact just mentioning that TRUE argument returns not echo’s

    • Steve Lescure says:

      Good suggestion. If you want to use this technique, make sure WP_DEBUG_LOG in wp-config.php is set to “TRUE”, otherwise nothing is written out. The debug.log file will show up within the directory wp_content.

  • Steve Lescure says:

    Really helpful article. When I first started programming with WordPress/PHP I found debugging really mystifying.

Pingbacks