Template Parts

If you’re using a theme with Theme Blvd Framework prior to 2.5, see the older version of this article, Template Parts (legacy).

Working with a theme framework like this one that utilizes action hooks to control just about everything can provide you with a completely dynamic child theme development experience. With that said, among some other more complex themes advertized as “frameworks” I feel that there is a certain element that becomes lost in this process. And that’s the luxury of actually getting a look at your HTML markup and WordPress theme tags outside of deeply-hooked PHP functions.

When opening a standard theme file within the Theme Blvd framework to see how it’s constructed (i.e. page.php, single.php, archive.php, etc.), it’s nice to be presented with something we’re all familiar with in the basics of WordPress theme development. To do this meant the outer HTML markup had to be crafted just right to give you the most flexibility from your child theme, while still keeping most items hooked within.

And so while these common top-level theme files are not intended to be edited, it is at least possible, as a last resort. Also, this allows us to get a visual representation of the outer theme structure, without having to just inspect our live website in the web browser.

So, then what files are we intended to edit?

And this question brings us to our big point – As a WordPress theme developer, you shouldn’t completely lose the ability to work with some basic HTML and WordPress theme tags. With our framework, you can forget about copying and pasting the same wrapping HTML code into the common theme files like page.php, single.php, etc, and instead just work with the template parts nested within the core of the standard theme files.

These template parts are going to smaller files with less code, that are easier to manage, allowing you to edit more specifically the area you want, without dragging all the outer stuff with them.

Working with Default Template Parts

The table below outlines the default template files of Jump Start 2. If you’re using another theme with Theme Blvd Framework 2.5+, there may be slight variations, but it’ll be more-or-less the same.

Working within the scope of the content files that already exist, it’s very easy to make changes. Simply copy the default files from the parent theme directory to your child theme and make your edits.

File Description
content.php Single post and individual post of a blog
content-404.php 404 (not found) page
content-attachment.php Single attachment post
content-grid.php Individual post of a post grid
content-list.php Individual post of a post list
content-mini-grid.php Individual post of a mini post grid
content-mini-list.php Individual post of a mini post list
content-page.php Static page, with default page template
content-page-search.php Wrapping content of search results
content-search-result.php Individual post in a search results list
content-showcase.php Individual post in a post showcase
content-template_archives.php Content of “Archives” page template
content-template_sitemap.php Content of “Sitemap” page template

Changing Which Content Files Are Called

As you dig deeper, you may find that want to call your own custom template parts for different scenarios. This is possible with the way the framework calls get_template_part() (a default WordPress function), and how we filter the values passed in.

Note: Are you trying to just change the entire post display for a post archive? For example, maybe you want your archives to display posts in a grid, instead of a blog. This wouldn’t involve changing the template part; instead, see Archive Post Displays.

Identifying the Template Part ID

In order to create custom template parts, you need to first know the ID the framework uses for the template part you want to target. This will be needed later when you filter in your template part from your child theme’s functions.php.

Blog and Single Posts
ID Default Value Resulting File
blog blog content-blog.php
blog_paginated blog content-blog.php
single single content-single.php
attachment attachment content-attachment.php

Notes: Because content-blog.php and content-single.php don’t exist, the default content.php file is called. So if you wanted to separate the display of blogroll posts vs the single post, you could simply create these files in your child theme, and they’ll automatically take effect.

Post Grids
ID Default Value Resulting File
grid grid content-grid.php
grid_paginated grid content-grid.php
grid_mini mini-grid content-mini-grid.php

Notes: Here we can see that (by default), whether a post grid is paginated or not, it will use content-grid.php. And for a mini post grid, content-mini-grid.php is used.

Post Lists
ID Default Value Resulting File
list list content-list.php
list_paginated list content-list.php
list_mini mini-list content-mini-list.php

Notes: Here we can see that (by default), whether a post list is paginated or not, it will use content-list.php. And for a mini post list, content-mini-list.php is used.

Post Showcase
ID Default Value Resulting File
showcase showcase content-showcase.php
showcase_paginated showcase content-showcase.php

Notes: Here we can see that (by default), whether a post showcase is paginated or not, it will use content-showcase.php.

Pages
ID Default Value Resulting File
page page content-page.php
naked_page page content-page.php
404 404 content-404.php
search page-search content-page-search.php
search_results search-result content-search-result.php

Notes: When dealing with a standard page, we can see that whether we use the “Default” page template or apply the “Naked Page” page template, by default the same file content-page.php is used.

Note that the search ID is used for the template to construct the outer wrap around the search results list, while the search_results ID is used for the individual posts that get displayed within the search results list.

Changing the Template Part ID

Now that you’ve identified the template part ID that corresponds to what you want to change, you can filter it in. To do this, you can take advantage of the themeblvd_template_part filter, which is applied every time a template part is called.

This filter is applied on the value, with the additional parameter of the $id passed in.

function my_template_part( $part, $id ) {

	if ( $id == 'page' ) {
		$part = 'my-page';
	}

	return $part;
}
add_filter( 'themeblvd_template_part', 'my_template_part', 10, 2 );

In the snippet above, we’re changing the template part used for pages to use a custom file called content-my-page.php. Because this filter is applied to ALL template parts, I first wrote a condition to check that $id was equal to the ID I wanted to target, which is page. And when it is, I’m changing the returned value to my-page.

Create Your Template Part File

And lastly, you obviously need to create the template file you’ve referenced, and put it in the root directory of your child theme. It will be named in the content-{value}.php format.

So, in reference to the previous code snippet, we’d now create a file called content-my-page.php, and place it in our child theme. It will now be used to display the content of pages.

In-Depth Example: Custom Post Types

Now, the example above isn’t all that practical, but was just meant to demonstrate how the filter works in its most basic sense. — Aside: If we wanted to customize the display of pages, there really wouldn’t be any reason to filter in a whole new template part file. We’d simply copy the default content-page.php to our child theme and edit it.

So, let’s look at a more practical example, where we can break down everything we’ve learned in this article.

Note: Feel free to skip to the code.

Setting up the Scenario

The most popular scenario I get asked about when dealing with template parts is with custom post types. For example, let’s say we want to create a custom post type for Books, which we’ve registered as book.

After you’ve created your post type for Books, you’ll see that the framework is using the default content.php to display the content of each book post, which is going to match your standard posts. But I’m guessing you’ve made it this far in the article, because you want something different to display!

What You Probably Want to Do, but Shouldn’t

Well, if you’re experienced with WordPress theming, your first instinct is going to copy the theme’s single.php file to your child theme, re-name it to single-book.php, and start editing away. STOP!

This is the point in the process where you stop what you’re doing and bear with me. In most generic themes, yes this is what you would probably do. And if you wanted to do this with your Theme Blvd theme, you absolutely could. But, I’m here to tell you there’s a better, less messy way.

Why would this be messy? — What happens if in the next update to the theme, we make some slight structural HTML change that effects single.php? When you update, it will be fairly time consuming to identify this change and incorporate it back in to the file in your child theme.

This is why we separate out the content into a separate file. This separate file — i.e. the “template part” — is smaller, easier to read, and will contain less code to manage.

Code to Filter in a New Template Part for Custom Post Types

The Single Post

Okay, first let’s keep it simple, and continue to expand on our code. When a single post of type book is displayed, we want to use a file called content-book.php in our child theme.

So, let’s filter this in from our child theme’s functions.php. From the tables above, we can identify that the ID of the template part we’re targeting is single.

function my_template_part( $part, $id ) {

	// "Book" single posts
	if ( $id == 'single' && get_post_type() == 'book' ) {
		$part = 'book';
	}

	return $part;
}
add_filter( 'themeblvd_template_part', 'my_template_part', 10, 2 );

Now, you just need to create an actual file content-book.php in your child theme. The fastest way to get started with this would probably just be to copy content.php to your child theme from the parent theme and rename it — then start editing it.

Posts in Different Scenarios

Because our filter is applied to ALL template parts, we can begin to get sucked down a rabbit hole of possibilities. Previously, we identified the single post, but what about when a Book is displayed in other post displays?

For example, maybe want to setup a post grid of books, but we want them display differently than standard posts would in a grid. From the tables above, we can see that grid and grid_paginated are the two ID’s we need to target. So, let’s create a file content-grid-book.php.

Sure, we could write out a whole new function and filter it onto themeblvd_template_part, but it might be more efficient to just handle all this in a single function, expanding on what we’ve already written above.

function my_template_part( $part, $id ) {

	if ( get_post_type() == 'book' ) {

		// "Book" single posts
		if ( $id == 'single' ) {
			$part = 'book';
		}

		// "Book" post grid
		if ( $id == 'grid' || $id == 'grid_paginated' ) {
			$part = 'grid-book';
		}
	}

	return $part;
}
add_filter( 'themeblvd_template_part', 'my_template_part', 10, 2 );
Multiple Post Types, a More Dynamic Way

All right, so what happens when you start adding multiple post types? You’ve got Books. Now what happens when you add Movies (post type: movie) and Songs (post type: song)?

I guess we could copy out the above code three times, change around the values, and call it a day. But instead, let’s start to think more efficiently. Let’s set up a system that will handle all three post types, and any we add in the future.

Let’s set it up like this: All custom post types will use a file content-{post_type}.php for single posts and content-grid-{post_type}.php for posts in a grid.

function my_template_part( $part, $id ) {

	if ( get_post_type() != 'post' ) {

		// Single posts
		if ( $id == 'single' ) {
			$part = get_post_type();
		}

		// Post grid
		if ( $id == 'grid' || $id == 'grid_paginated' ) {
			$part = 'grid-'.get_post_type();
		}
	}

	return $part;
}
add_filter( 'themeblvd_template_part', 'my_template_part', 10, 2 );

Note: When we use the condition get_post_type() != 'post', we’re checking that it’s any post type that’s not the WordPress standard post type. And since the framework calls pages and attachments (also WordPress post types) separately, we don’t have to worry about those.

So, the above code snippet will create our dynamic system. Now, we just need to make sure to create the corresponding files in our child theme for all of these post types we’ve registered.

  1. content-book.php
  2. content-grid-book.php
  3. content-movie.php
  4. content-grid-movie.php
  5. content-song.php
  6. content-grid-song.php