How to pass data to WordPress template parts

Aug 28, 2019

If you’re looking for a solution on how to pass data (such as variables, objects and arrays) to WordPress template parts (with get_template_part() function), you’re in luck. There are actually quite many ways to achieve that. While they all works at some extend, some are definitely better than others. In this article I’m going to show you a few of them and also try to explain when to use each of them.

These are your options

The “include(locate_template( ‘my-partial.php’, false, false ))” method

The most simple, although not the best, way to pass variables to your template parts is to combine include and locate templates like this:

<?php

$my_variable = "An example string";

include( locate_template( 'my-partial.php', false, false ) );
// refers to my-partial.php in your theme folder

and then use the variable like this:

<?php

echo esc_html( $my_variable );
// escapes and outputs "An example string"

This pattern doesn’t explain itself too well and can be confusing for other developers who might touch the project, so in general you should avoid using this. For a quick an dirty “I just want to make this work” kind of situations you should take a look at the next “‘set_query_var()’ method”.

The “set_query_var()” method

This method is explained pretty well in this StackOverflow answer so you should take a look there if you would like to see why this works the way it does. But in a nutshell you can use set_query_var() like this:

<?php

set_query_var( 'my_variable', "An example string" );
get_template_part( 'my-partial.php' );

and then use the data like this:

<?php 

// set_query_var uses extract() behind the scenes so we can just use my_variable as $my_variable

echo esc_html( $my_variable );
// escapes and outputs "An example string"

This definitely works and it’s ok to use if you just need to pass some data into a template here and there.

The “set and get params from $GLOBALS” method

This is by far my favorite way of passing data into a template part. It’s quite similar to the set_query_var method but a bit more verbose on purpose (it’s easier to other developers to understand where the data comes from). It also uses dedicated $GLOBAL array key instead of polluting the WordPress query vars to avoid some possible bugs caused by caused by setting multiple query vars with a same name.

Create a modified get_template_part() function and a completely new get_template_param() function into your functions.php like this:

<?php

function get_template_part_with_params( $slug, $name, $params ) {
$templates = array();
	$name      = (string) $name;

	if ( '' !== $name ) {
		$templates[] = "{$slug}-{$name}.php";
	}

	$templates[] = "{$slug}.php";

	// Save params to globals
	$GLOBALS['my_template_params'] = $params;

	locate_template( $templates, true, false );

	// Empty params to prevent some possible bugs
	$GLOBALS['my_template_params'] = [];
}

function get_template_param( $template_param ) {
	if ( isset( $GLOBALS['my_template_params'][ $template_param ] ) ) {
		return $GLOBALS['my_template_params'][ $template_param ];
	}

	return false;
}

and then you can use it like this:

<?php

$params = [
	'title' => 'My title',
	'content' => 'My content',
	'post_id' => get_the_ID(),
];

get_template_part_with_params( 'my-partial', '', $params );
// refers to my-partial.php in your theme folder
<?php

$title = get_template_param( 'title' );
$content = get_template_param( 'content' );
$post_id = get_template_param( 'get_the_id' );

?>

<?php if ( $title ) : ?>
	<h2><?php echo esc_html( $title ); ?><h2>
<?php endif; ?>
<?php if ( $content ) : ?>
	<p><?php echo esc_html( $content ); ?></p>
<?php endif; ?>

<?php

$params = [
	'post_id' => $post_id,
];

get_template_part_with_params( 'my-sub-partial', '', $params );
// refers to my-sub-partial.php in your theme folder
<?php

$post_id = get_template_param( 'get_the_id' );

?>

<p><?php echo esc_html( $post_id ); ?></p>

As you can see, this way you can not only pass data into your templates, but you can actually start to abstract your data away from your partials in a way that you could technically use all the partials in any context with any kind of data.