Currently reading: Stories of Your Life and Others by Ted Chiang

Move your WordPress theme's templates into a subdirectory

Building on our (mostly unnecessary) add_filters() function to attach a callback to multiple hooks at once, we can adjust how WP's template hierarchy works. Yes, page-specific templates could already go in a `page-templates` directory, but this hook lets all of your templates go into a directory of your choosing.

$get_query_template_hooks = [
    '404_template_hierarchy',
    'archive_template_hierarchy',
    'attachment_template_hierarchy',
    'author_template_hierarchy',
    'category_template_hierarchy',
    'date_template_hierarchy',
    'embed_template_hierarchy',
    'frontpage_template_hierarchy',
    'home_template_hierarchy',
    'index_template_hierarchy',
    'page_template_hierarchy',
    'paged_template_hierarchy',
    'privacypolicy_template_hierarchy',
    'search_template_hierarchy',
    'single_template_hierarchy',
    'singular_template_hierarchy',
    'tag_template_hierarchy',
    'taxonomy_template_hierarchy'
];

add_filters($get_query_template_hooks, function ($templates) {
    $more = array_map(function ($template) {
        return "templates/{$template}";
    }, $templates);

    return array_merge($more, $templates);
});

unset($get_query_template_hooks);

A bit fussy, yes, but there seems to be no straightforward way to mess with WP's template hierarchy. This is in large part due to WP's otherwise handy locate_template() function running no filters whatsoever. All we get access to is template_include which is after the template-picking has been done!

While you can make this work by grabbing the already-chosen template and doing another locate_template() call on its basename(), that's not what we're trying to do here. We want to tell WP to search more spots for templates than it would normally. Hence the array of filter names above: According to the source, these are all of the available hook names that can be used to adjust where get_query_template() looks for template files.

In the code above, all we're doing is adding templates/ to the list. Now whenever WP goes to look for, say, search.php or archive.php, it'll check your theme's templates subdirectory. This allows for a clean theme directory setup like this:

/super-awesome-theme-2025
↳…./assets
↳…./blocks
↳…./includes
↳…./partials
↳…./templates
↳….functions.php
↳….index.php
↳….style.css

Is such a setup superfluous? Sure. But doesn't it look nice?

Leave a comment

Your email address will not be published. Required fields are marked *