In this lesson of the WordPress theme tutorial for beginners we will dive more into templates. We’ll learn about template parts and implement it for reusability. And we’ll add more of WordPress’ default templates to our theme.

But before we start adding more template files we need to know why we should bother with template parts.

Template parts: More flexible building blocks

Template parts work exactly like get_header() and get_footer() which we learned about in part 2, but are not limited to these files. You can use template parts for whichever file you want!

Themes commonly use a template part for posts in a loop. Usually many templates such as category, archive, and search results usually display each post in a loop the same way. It’s therefore it’s a very good idea to separate out the post loop output into one file. This way you don’t have to repeat it in every template.

Let’s “convert” some of our existing code into template parts before we start making more templates!

Creating a post loop template part

Create a new empty file in our theme folder; called content-loop.php. You can name the template parts whatever you want. But you cannot name them the same as any of WordPress’ defined templates. In our index.php, locate everything you have inside the loop, cut it out and paste it inside content-loop.php.

Inside the now empty loop in index.php, use the function call get_template_part() and define your template part file as parameter (without the .php extension). This is what it should look like in both files:

index.php
...
	while (have_posts()) : the_post(); 
		get_template_part('content-loop');
	endwhile;
	the_posts_pagination();
...
content-loop.php
<article <?php post_class(); ?>>
	<h2><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2>
	<?php if (has_post_thumbnail()) {
		the_post_thumbnail();
	} ?>
	<?php the_excerpt(); ?>
	<?php the_category(); ?>
</article>

If you refresh your front page you should see absolutely no difference.

Great! Now that our index.php is nice and clean, we can use it as a base to duplicate into more templates. Below I will go through how to add category template and search results template, but I encourage you to create more templates for more control on design of your theme.

Adding a category template

If you refer back to the WordPress’ hierarchy of templates, you can see that for post categories, WordPress will look for the template named category.php. We’ll create that one first.

In your theme folder, make a copy of the index.php file, and rename the copy category.php.

And.. that’s it. You are basically done…!

However, we will add one detail; we want to show a title that tells us that we are at a category page for posts in category named X. WordPress has a function for this that you can use in all archive templates (category, tags, date archives), the_archive_title. Let’s add it before the loop, inside a <h1> tag.

category.php
<?php get_header(); ?>
<h1><?php the_archive_title(); ?></h1>
<?php
if (have_posts()) {
...

If you view a post category page, you should see something like this, with the archive title “Category: <NameofCategory>”. PS: If you want to change the output of the archive title (for example not showing “Category: “), you can add a filter to get_the_archive_title. The documentation page shows a great example of how to do just that.

Well, that was easy! Let’s handle search results template next.

Adding a search results template

The procedure is exactly the same as we did for category templates. This time, make a copy of category.php, and rename the copy into search.php.

All we need to fix is the title. The archive title function we used in category template unfortunately does not work very well for search results template. In fact, there exists no simple function in WordPress that outputs a title for us.

But we can easily make one ourselves, and at the same time I’ll demonstrate how to output a dynamic variable and still keep the text translatable.

PHP has two useful functions, printf() and sprintf(). They do the same, except that printf outputs it (like echo) and sprintf returns it, so we can store it in a variable. After we put the text as first parameters, we can add dynamic variables as arguments, which is then injected into the text. Inside those, we can use the translatable text functions, __() and _e(). I recommend that you read a little bit about how printf or sprintf works, as I will not go into further detail here.

WordPress offers a simple function to get the string that was searched; get_search_query(). With that said, let’s replace the archive title function with this;

search.php
<h1><?php printf(__('Search: %s', 'wptutorial'), get_search_query()); ?></h1>

What the above code does is from the inside out; defining a translatable text “Search: %s” which is put inside a printf which echoes the string, and replaces the string constant (%s) with the second argument; which is get_search_query().

As a result, we get a title like this when searching for “er”:

Nice! Another template done. As for the last part of this lesson, we will go into our single post template and add something very common in WordPress; the comments template.

Adding a comments template to single post

In our single.php, after the post article, we want to show comments. The comments should output a list of previous comments, and a form to add a new comment.

Comments template is a template file you can add to your theme, but WordPress actually has its own default comments template output. If you don’t have comments.php in your theme, requesting the comments template will return WordPress’s default output for it. This is what we will do in this tutorial.

We only want to call the comments template if the post has activated comments (it’s a setting for each post and a global site setting). So we add an if check to check if the comments are allowed with comments_open() and if it returns true, we request comments template with comments_template(). Keep in mind that all of this must happen within the loop. I added it after the end of </article>, right before the loop closes.

single.php
...
		<p><?php _e('Author', 'wptutorial'); ?>: <?php the_author(); ?></p>
	</article>
	<?php 
	if (comments_open()) {
		comments_template();
	}
	endwhile;
} else {
	?><p><?php _e('No posts, sorry.', 'wptutorial'); ?></p><?php
...

If you visit a single post that has allowed comments (I added a comment just to show you the list of comments as well); you’ll get this beautiful (ahem) default comments template:

Now, you can (and it is often encouraged) create your own comments.php in your theme, which will override WordPress’ default output. I am not going through creating a comments template in this tutorial though, as WordPress’ default output works just fine as long as you style it properly. If you inspect the HTML, there are plenty of wrappers and classes available.

Documentation on methods used