Wordpress - Passing a variable to get_template_part
As posts get their data set up via the_post()
(respectively via setup_postdata()
) and are therefore accessible through the API (get_the_ID()
for e.g.), let's assume that we are looping through a set of users (as setup_userdata()
fills the global variables of the currently logged in user and isn't useful for this task) and try to display meta data per user:
<?php
get_header();
// etc.
// In the main template file
$users = new \WP_User_Query( [ ... ] );
foreach ( $users as $user )
{
set_query_var( 'user_id', absint( $user->ID ) );
get_template_part( 'template-parts/user', 'contact_methods' );
}
Then, in our wpse-theme/template-parts/user-contact_methods.php
file, we need to access the users ID:
<?php
/** @var int $user_id */
$some_meta = get_the_author_meta( 'some_meta', $user_id );
var_dump( $some_meta );
That's it.
Update (WP >= v5.5)
As pointed out in the comments, current versions of WP offer a third parameter for [get_template_part()][1]
: array $args
. So from this version on, you do not need to use set_query_var( 'foo', 'bar' )
anymore. Example:
<?php
get_header();
// etc.
// In the main template file
$users = new \WP_User_Query( [ ... ] );
foreach ( $users as $user )
{
$args = (array) $user;
get_template_part( 'template-parts/user', 'contact_methods', $args );
}
Then, in our wpse-theme/template-parts/user-contact_methods.php
file, we need to access the users ID:
<?php
/** @var array $args */
$some_meta = get_the_author_meta( 'some_meta', $args['ID'] );
var_dump( $some_meta );
The explanation is actually exactly above the part you quoted in your question:
However,
load_template()
, which is called indirectly byget_template_part()
extracts all of theWP_Query
query variables, into the scope of the loaded template.
The native PHP extract()
function "extracts" the variables (the global $wp_query->query_vars
property) and puts every part into its own variable which has exactly the same name as the key. In other words:
set_query_var( 'foo', 'bar' );
$GLOBALS['wp_query'] (object)
-> query_vars (array)
foo => bar (string 3)
extract( $wp_query->query_vars );
var_dump( $foo );
// Result:
(string 3) 'bar'
The hm_get_template_part
function by humanmade is extremely good at this and I use it all the time.
You call
hm_get_template_part( 'template_path', [ 'option' => 'value' ] );
and then inside your template, you use
$template_args['option'];
to return the value. It does caching and everything, though you can take that out if you like.
You can even return the rendered template as a string by passing 'return' => true
into the key/value array.
/**
* Like get_template_part() put lets you pass args to the template file
* Args are available in the tempalte as $template_args array
* @param string filepart
* @param mixed wp_args style argument list
*/
function hm_get_template_part( $file, $template_args = array(), $cache_args = array() ) {
$template_args = wp_parse_args( $template_args );
$cache_args = wp_parse_args( $cache_args );
if ( $cache_args ) {
foreach ( $template_args as $key => $value ) {
if ( is_scalar( $value ) || is_array( $value ) ) {
$cache_args[$key] = $value;
} else if ( is_object( $value ) && method_exists( $value, 'get_id' ) ) {
$cache_args[$key] = call_user_method( 'get_id', $value );
}
}
if ( ( $cache = wp_cache_get( $file, serialize( $cache_args ) ) ) !== false ) {
if ( ! empty( $template_args['return'] ) )
return $cache;
echo $cache;
return;
}
}
$file_handle = $file;
do_action( 'start_operation', 'hm_template_part::' . $file_handle );
if ( file_exists( get_stylesheet_directory() . '/' . $file . '.php' ) )
$file = get_stylesheet_directory() . '/' . $file . '.php';
elseif ( file_exists( get_template_directory() . '/' . $file . '.php' ) )
$file = get_template_directory() . '/' . $file . '.php';
ob_start();
$return = require( $file );
$data = ob_get_clean();
do_action( 'end_operation', 'hm_template_part::' . $file_handle );
if ( $cache_args ) {
wp_cache_set( $file, $data, serialize( $cache_args ), 3600 );
}
if ( ! empty( $template_args['return'] ) )
if ( $return === false )
return false;
else
return $data;
echo $data;
}
I was looking around and have found a variety of answers. Its seems at a native level, Wordpress does allow for variables to be accessed in Template parts. I did find that using the include coupled with locate_template did allow for variables scope to be accessible in the file.
include(locate_template('your-template-name.php'));