I was building a custom WordPress theme for a client site when I came across a frustrating problem with variable scope. I was modularising the theme using template parts, which get loaded using the get_template_part
function.
This particular template was displaying a list of posts of a custom post_type from a call to the get_posts
function and I wanted to be able to pass certain variables to the template part which rendered part of the display.
Within the loop this generally isn’t a problem, since most functions access global $post variables and such, so no variable passing is required at a template level.
However, when dealing with custom post types and function calls outside of the loop, there are variables which need to be passed to functions to make them work.
The problem is that variables you define in the template are not available for use within the template part.
For example, if we define a variable $post_id
in our main template file:
<?php get_template_part('parts/header'); ?> <div id="content"> <?php while (have_posts()) : the_post(); ?> <?php $post_id = $post->ID; ?> <div class="entry"> <?php get_template_part('parts/postbit', 'loop'); ?> </div> <?php endwhile; ?> </div> <?php get_template_part('parts/sidebar'); ?> <?php get_template_part('parts/footer'); ?>
… and then try to use $post_id
in our template part:
<?php $thumbnail = get_the_post_thumbnail($post_id); ?> <h2 class="index-title"><a href="<?php echo get_permalink($post_id) ?>" rel="bookmark"><?php echo get_the_title($post_id); ?></a></h2> <div class="post-thumbnail"><?php echo $thumbnail; ?></div> <div class="entry-loop"> <?php echo get_the_excerpt($post_id); ?> </div>
… the variable will not be defined for use. Yes, I know there are other ways of achieving what I am trying to do in the examples, using built-in WordPress functions, but this is just a contrived example to demonstrate the problem.
Fortunately, there is an alternative method of including template parts which does pass variable scope – use a PHP include
paired with the locate_template
function to find and include the part you need:
<?php get_template_part('parts/header'); ?> <div id="content"> <?php while (have_posts()) : the_post(); ?> <?php $post_id = $post->ID; ?> <div class="entry"> <?php include(locate_template('parts/postbit-loop.php')); ?> </div> <?php endwhile; ?> </div> <?php get_template_part('parts/sidebar'); ?> <?php get_template_part('parts/footer'); ?>
Source: WordPress StackExchange: Form Submitting Error with get_template_part()
Claudio Rimann says
Just stumbled upon this article while having a similar problem. I wanted to get some data out of variable $term on a template-part.
While your solution (include + locate_template) didn’t really work for me, i finally just added “global $term” in my template part and worked around it that way.
Have to say, i’m completely unsure if this is the best way around this, but it worked…
Eric Blosch says
I’ve been building with ACF Pro, and ran into this exact problem. Nice solution, thanks.