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 and at the same time simple knowledge. Every WordPress developer should know how to manage it. Below you will find fully covered WordPress theme files structure and the order of how these files are connected (their hierarchy).
- Theme files connections (theory)
- Page types and file names
- Posts
- Static page
- Post
- Custom post type
- Attachment
- Archives
- Category
- Tag
- Taxonomy
- Post type archive page
- Author page
- Archive page of date (day, month, year)
- 404 page
- Search page
- Main page
- Blog page
- Embeds
- Non-ASCII characters handling
- How it works
- Filters
- Other theme files
Theme files connections (theory)
Hierarchy, in this case, is a sequential files search for multiple preprogrammed file names that are suitable for the output of the specific page. I.e. there is a list of filenames that are checked for the existence one by one, and as soon as the file is found (it exists), the check stops and the found file is used as a template for the page; the search is made from the more specific hierarchy to the less one.
For example, we go to the category page "Plugins": http://example.com/category/plugins (the page has slug plugins and id 25). Then, to generate the code of the page, WordPress will start checking for the existence of the following files one by one (the scan will abort on the first existing file):
- category-plugins.php
- category-25.php
- category.php
- archive.php
- index.php
The complete diagram for all kinds of pages and their files looks like this:
An interactive version of the diagram
Another diagram (old one), perhaps it is more clear:
menuPage types and file names
Below is a list of pages and their theme files. In this section, explaining the image of the hierarchy of theme files (which is shown above). Also, you will find different types of site pages and their corresponding list of PHP files. Such files should be located in the folder of the WordPress theme.
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
, then plain.php
, and then text-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
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.
menuFilters
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).
menuOther theme files
The files below are also used in the theme, but they are simply includable and do not participate in the hierarchy. For example, file sidebar.php is included in any theme file through get_sidebar().
A whole list of such non-hierarchical 'includable' files:
- functions.php - always is included automatically when the theme is loaded.
- header.php - get_header()
- sidebar.php - get_sidebar()
- footer.php - get_footer()
- searchform.php - get_search_form()