Question

While I've typically used include or require on their own to save long term code maintenance I've started to use get_template_part and locate_template as using built in WordPress stuff is always best.

My question is are you supposed to be able to pass variables through to the results of either get_template_part or locate_template?

<?php
$var = get_option( 'my-custom-option' );

get_template_part( 'custom-template-part' );
?>

In the code above the $var would be printed inside the custom template but the variable doesn't seem to work. Am I missing something or is this expected behaviour?

I've found that they don't pass in the instance above or when using locate_template

<?php
locate_template( 'custom-template-part.php', true );
?>
Was it helpful?

Solution

Like MathSmath wrote, get_template() does not support the re-use of your variables.

But locate_template() infact does no inclusion at all. It just locates a file for inclusion.

So you can make use of include to have this working just like you expect it:

include(locate_template('custom-template-part.php'));

$var from your example can be used in the template part then.

A related question with a more technical explanation of the variable scope and get_template(): Form Submitting Error with get_template_part()

OTHER TIPS

A neat solution found in the codex

So if you are looping thru custom posts, you can do this:

foreach ($custom_posts as $custom_post) {
    set_query_var( 'my_post', $custom_post );
    get_template_part( 'content', 'part' );
}

And in that template itself, you will automatically get a $my_post.

I've had trouble with this too (while trying to get a custom query to work with a template part). The short answer is: no, the template part doesn't automatically inherit custom vars the way a regular include does.

Both get_template_part() and locate_template() eventually use the load_template() function to actually load the file (using a require). This function globalizes the following vars:

$posts, $post, $wp_did_header, $wp_did_template_redirect, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID

However, no other vars appear to be available from inside the template part. I guess since the actual require is wrapped in a function, the scope changes or something?

Anyhoo, I'd try globalizing any additional vars you need to pass, then calling up those globals from your template part.

Just my two cents for future references, a workaround at least in Wordpress 3.5 is to add the variable to $wp_query->query_vars.

I needed my global _vk_errors inside a template part and just did $wp_query->query_vars['_vk_errors'] = $_vk_errors; before calling get_template_part().

Wordpress 5.5+

The $args parameter was added to locate_template https://developer.wordpress.org/reference/functions/locate_template/

Pass data

$data = [
  'foo' => 'Hello',
  'bar' => ', Wordpress 5.5',
];
locate_template('your-template.php', true, true, $data);

your-template.php

//handle passed arguments through $args
echo $args['foo'] . $args['bar']; // "Hello, Wordpress 5.5"
// or use extract($args);
extract($args);
echo $foo . $bar; // "Hello, Wordpress 5.5"

locate_template uses load_template, that since 5.5 can pass additional arguments to the template as well.

https://developer.wordpress.org/reference/functions/load_template/

So do all the template functions that use locate_template:

get_header, get_footer, get_sidebar, get_template_part.

https://developer.wordpress.org/reference/functions/get_header/ https://developer.wordpress.org/reference/functions/get_footer/ https://developer.wordpress.org/reference/functions/get_sidebar/ https://developer.wordpress.org/reference/functions/get_template_part/

There is my simple function solving variable problem. It's doing same thing as Wordpress do in get_template_part() function. Just copy and paste to function.php

function getTemplatePart($slug = null, $name = null, array $params = array()) {
    global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;

    do_action("get_template_part_{$slug}", $slug, $name);
    $templates = array();
    if (isset($name))
        $templates[] = "{$slug}-{$name}.php";

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

    $_template_file = locate_template($templates, false, false);

    if (is_array($wp_query->query_vars)) {
        extract($wp_query->query_vars, EXTR_SKIP);
    }
    extract($params, EXTR_SKIP);

    require($_template_file);
}

Example of usage in template

$params = array(
    'utm_source' => 'footer'
);
while ($posts->have_posts()) {
    $posts->the_post(); 
    getTemplatePart('content', 'heighlight', $params);
}

In the content-heighlight.php is accessible variable with name $utm_source and value footer

You can just wrap the get_template_part, store a model object in a global var, and clear it later. Here is how we have been doing in our projects:

functions.php

$model = null; // this is a global variable 
function my_get_template_part($slug, $name = null, $templateModel = null) {
    global $model;
    $model = $templateModel; // set the global var to the provided model object
    get_template_part($slug,$name); 
    $model = null; // clear the global var
}

function get_model() {
    global $model;
    return $model;
}

Usage in the main template:

<?php my_get_template_part('template-parts/xxxx','xxx',array('test1'))?>

Accessing the provided model in the template-part :

<?php $model = get_model() ?>

This way, you don't have to copy & paste the original get_template_part function to your own function in case its implementation may change later by WP developers.

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top