56

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 );
?>

7 Answers 7

66

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

4
  • Good call. I didn't notice that locate_template() has a param that lets you optionally call load_template() with the results (which get_template_part does), or just return them. I'm looping back on a current project to update code using this approach...thanks!
    – MathSmath
    Commented Nov 24, 2010 at 18:07
  • shortly after I posted here I ended up using the same method. Commented Nov 24, 2010 at 21:22
  • 21676 addresses this, but doesn't look like it'll be committed.
    – Ian Dunn
    Commented Feb 19, 2013 at 19:05
  • Maybe Im wrong but: locate_template() infact does inclusion, if the parameter is set as true -as in the question. (default is false, so dont paste the questions version into accepted answer.) You could also just use set_query_var('var', $var); and use your get_template_part() as normal. Then you also have the default Worpdress variables accessible within the templatefile, as @MathSmath mentioned. Commented Oct 7, 2017 at 14:29
14

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.

2
  • This would be the correct answer if the example code was answering the question. (Passing option, not complete posts array) Commented Oct 7, 2017 at 14:36
  • This works beautifully to pass extra information to the included template. It also works for wc_get_template_part in WooCommerce which no doubt extends default WP.
    – nabrown
    Commented May 3, 2019 at 19:00
9

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.

5

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

4

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/

2

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

1
  • Interesting function. Are all the globals and query vars usually accessible in normal template files?
    – christian
    Commented Dec 3, 2014 at 23:09
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.