You know what really grinds my gears? Code duplication. And you know where you can find plenty of that? In WordPress themes!

This has gotten a little better recently, thanks to get_template_part().

Still, for each main template file you have to repeat the calls to get_header(), get_sidebar() and get_footer(), as well as any HTML that defines your basic layout.

Here’s an example archive.php file:

<?php get_header(); ?>

<section id="primary">
	<div id="content" role="main">
		<?php while ( have_posts() ) : the_post(); ?>

		<?php get_template_part( 'content', get_post_format() ); ?>

		<?php endwhile; ?>
	</div>
</section>

<?php get_sidebar(); ?>

<?php get_footer(); ?>

Even with the creative use of get_template_part(), all the code around it will need to be added to single.php, tag.php etc. etc.

What you would like to do is put all that common code into a single file, and call it, say, wrapper.php:

<?php get_header( my_template_base() ); ?>

<section id="primary">
	<div id="content" role="main">
		<?php include my_template_path(); ?>
	</div>
</section>

<?php get_sidebar( my_template_base() ); ?>

<?php get_footer( my_template_base() ); ?>

and leave archive.php with only the specific code:

<?php while ( have_posts() ) : the_post(); ?>

	<?php get_template_part( 'content', get_post_format() ); ?>

<?php endwhile; ?>

Here’s what the template hierarchy looked like before:

{template}.php
    header-{foo}.php > header.php
    sidebar-{bar}.php > sidebar.php
    footer-{baz}.php > footer.php

and after:

wrapper-{template}.php > wrapper.php
    {template}.php
        header-{template}.php > header.php
        sidebar-{template}.php > sidebar.php
        footer-{template}.php > footer.php

Replace {template} with any template name: single, taxonomy-my_custom_tax etc.

Now you’re probably wondering what kind of voodoo you would have to do to make this work. In fact, the only magic ingredient you need is the often overlooked 'template_include' filter:

Paste that code into your theme’s functions.php file and you’re done: wrappers for all.

Note that you can have multiple wrappers: wrapper-single.php, wrapper-page.php etc. and that they can be overwritten, just like any other template, using a child theme.

This approach was inspired by Django’s template language, which supports template inheritance.