WordPress Theme Files Hierarchy
This post is about the names of the WordPress theme files. And it also reviews which file to include for showing the content of a specific page. This is very important, necessary, and at the same time very simple, for understanding, knowledge. Everyone who works with WordPress must have them. Below you will find fully covered WordPress theme files structure and the order of how these files are connected (their hierarchy).
An example of how a hierarchy works
For example, we go to the "My-Category" page http://example.com/category/my-category
. Here my-category
is the slug of this category. And the ID is 25
.
The slug and ID you can find on the edit-category admin page.
Then one of the files below will be responsible for the template of this WordPress page (files are checked one by one, the first existing file in the theme will be the template for this page):
category-my-category.php
category-25.php
category.php
archive.php
index.php
Hierarchy, in this case, is a consistent check for the existence of a template file. For the content of one page on the site, there may be several files. Checking which file will be used one by one. I.e., WordPress has a list of suitable file names, and each of the names is checked in turn for the physical existence of such a file, as soon as WordPress sees that the file exists, the search for a suitable file stops, and the found file is used as a template.
Other theme files
Also, WordPress has common connectable files. They do not participate in the hierarchy but need to be plugged in manually where necessary. For example, the sidebar.php file is included in the theme template file using the function get_sidebar().
A whole list of such 'includable' files:
functions.php
- always is included automatically when the theme loads.header.php
- get_header()sidebar.php
- get_sidebar()footer.php
- get_footer()searchform.php
- get_search_form()
Page types and file names
Now when we understand how the hierarchy works, let's look at all the file names that WordPress tries to find when you visit a particular page on the site.
The complete diagram for all kinds of pages and their files looks like this:
Now, I will describe this picture, make from it a list of site pages and the corresponding php files for them.
The files from the list below should be located in the theme directory.
Posts
Static page
{any_name}.php
(when the page template is used)page-{post_slug}.php
page-{post_id}.php
page.php
singular.php
-
index.php
Post
single-post-{post_slug}.php
single-post.php
single.php
singular.php
-
index.php
Custom post type
{any_name}.php
(for heirarchical posts with templates support. From WP 4.7)single-{post_type}-{post_slug}.php
single-{post_type}.php
single.php
singular.php
-
index.php
Attachment
{MIME_type_start}.php
{MIME_type_end}.php
{MIME_type_start}-{MIME_type_end}.php
attachment.php
single-attachment-{attachment_slug}.php
(allows you to specify a template for a single attachment)single-attachment.php
(same as attachment.php)single.php
singular.php
-
index.php
By the 'start' and 'end' of the MIME type, I mean the first and last part of the MIME which is separated by /. For example, if it is a text file with MIME type 'text/plain', then the existence of the following files will be checked: first
text.php
, thenplain.php
, and thentext-plain.php
.See the code of wp_get_mime_types() function for a complete list of MIME types.
Archives
Category
category-{slug}.php
category-{id}.php
category.php
archive.php
paged.php
(if a pagination page)-
index.php
Tag
tag-{slug}.php
tag-{id}.php
tag.php
archive.php
paged.php
(if a pagination page)-
index.php
Taxonomy
taxonomy-{taxonomy_name}-{slug}.php
taxonomy-{taxonomy_name}.php
taxonomy.php
archive.php
paged.php
(if a pagination page)-
index.php
Post type archive page
archive-{post_type_slug}.php
archive.php
paged.php
(if a pagination page)-
index.php
Author page
author-{nickname}.php
author-{id}.php
author.php
archive.php
paged.php
(if pagination page)-
index.php
Archive page of date (day, month, year)
date.php
archive.php
paged.php
(if a pagination page)index.php
404 page
404.php
index.php
Search page
search.php
index.php
Main page
front-page.php
- ('page' post type logic if a page is selected as a front page)
home.php
index.php
Blog page
The blog page appears when the 'page' is selected as a front page.
home.php
index.php
Embeds
The embed template file is used to render a post which is being embedded with REST API. Embedding appeared in WP 4.5 and allows you to embed your posts in other sites. See get_post_embed_url().
embed-{post-type}-{post_format}.php
embed-{post-type}.php
embed.php
To change the embedding content only, you can create a embed-content.php file in your theme and describe embed HTML in it. The original embed HTML is in the core file /wp-includes/theme-compat/embed-content.php.
Non-ASCII characters handling
Since WordPress 4.7, any dynamic part of a template name which includes non-ASCII characters in its name actually supports both the un-encoded and the encoded form, in that order. You can choose which to use.
Let's look at the page template hierarchy for a page named Hello World 😀
with the ID of 6:
page-hello-world-😀.php
page-hello-world-%f0%9f%98%80.php
page-6.php
page.php
singular.php
The same behavior applies to post slugs, term names, and author nicenames.
How it works in WP core
For the logic of order in which the files are connected is responsible the core file wp-includes/template-loader.php. If you study it, the file explains everything. But such a study is not so interesting, so I will explain it here in details.
First of all. template-loader.php file is connected after the whole WordPress environment is loaded. After the wp-load.php file is run and the main query is inited (see wp()). I.e. template-loader.php file is connected at the very end of the PHP script.
First runs the hook template_redirect. You can do some kind of checks in this hook and if you need redirect the user to another URL, you must use die() in it. I.e. if the hook changes something, then the work of template-loader.php file ends and the user is redirected.
Next triggers not interesting hook exit_on_http_head. It allows you to make something appear on the screen when there is HTTP HEAD request...
Next there are checks on all Conditional Tags. During these checks, WordPress detects which template file is more suitable for the current request. The conditional tag is checked, then another and another... As soon as one of the conditional tags is triggered, the corresponding function is called, which finds the appropriate template file and returns the path to it. All such functions are described in get_query_template().
Next - path to the theme file is defined! Now it runs through the template_include filter which allows us to modify the template file for the current request.
Next, the file connects to PHP and starts the visual part of the page generation.
Filters
You can change the file hierarchy through dynamic filters:
-
(type)_template_hierarchy - filters the array of filenames in the hierarchy by which to search for the desired file. From WP 4.7.
- (type)_template - filters the path to the template file that has already been defined.
All variants of type parameter can be found in the $type parameter of get_query_template() function. Here they are:
index
404
archive
post_type_archive
author
category
tag
taxonomy
date
home
front_page
page
paged
search
single
singular
attachment
comments_popup
Example of using such filter see in the answer to this question (rus).