Variable scope in WordPress template parts

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

Tags: ; ;

  • Share it!

2 Responses

  1. By Claudio Rimann on 24th December, 2013

    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…

  2. By Eric Blosch on 3rd May, 2016

    I’ve been building with ACF Pro, and ran into this exact problem. Nice solution, thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *