WordPress.org

Make WordPress Core

Opened 2 years ago

Last modified 16 months ago

#41362 new enhancement

Make locate_template() filterable to change the template locations

Reported by: kylejennings83 Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.8
Component: Themes Keywords: has-patch needs-testing 2nd-opinion
Focuses: template Cc:

Description

Right now WordPress expects all templates to reside in the root of your theme directory. We have all come across a theme with dozens of templates and well, that can get messy. With 6 lines of code we can easily, and vastly enhance the templating system.

This would provide a number of benefits:
1) This would allow developers to logical group functionally similar files / separates functional dissimilar files
2) It allows the root of the theme directory to be cleaned up and used for "resources" such as the functions.php and style.css files
3) By having the ability to pick and choose which templates go where, we can turn WordPress into an MVC application framework (personally what I use this technique for)
4) Related - this plays really nice with Timber
5) This lays the groundwork for future enhancements which I also use and plan to introduce shortly

Examples

Moving all templates with the "templates_path" filter

Say I wanted to move all my templates into a directory named "templates" because as mentioned, this theme I inherited has dozens of templates, maybe one for each page. A good start would be to just move all the templates into a directory named "templates":

<?php
function move_templates($path){
    return 'templates';
}
add_filter('templates_path', 'move_templates');

This filter would move ALL templates to the "templates" directory (and has the added effect of also moving the location of the header, footer ect ect files as well) . So now the root of our theme is nice and clean:

/twentyseventeen/
|-- /assets/
|-- /inc/
|-- /templates/
|-- functions.php
|-- index.php
|-- README.txt
|-- rtl.css
|-- screenshot.png
|-- style.css

Now obviously just moving dozens of templates into a different directory just moves the mess out of site, but that directory is still a mess and just a stew of unrelated templates.

Group related templates together with the "{$type}_templates_path" filter

To clean things up even more. Imagine if 10 of these templates were all children of the page "team". You could group them all together into a subdirectory of "templates" called "team" like so:

<?php

function move_team_pages($path = '', $type = null){
    $parent = get_page_by_title( 'team' );

    $parent_id = $parent->ID;
    $obj = get_queried_object();

    if($obj->post_parent == $parent_id)
        $path  = rtrim($path, '/') . '/' . 'team';


    return $path;

}
add_filter('page_templates_path', 'move_team_pages');

Now your theme might look something like:

/twentyseventeen/
|-- /assets/
|-- /inc/
|-- /templates/
     |-- index.php
     |-- single.php
     |-- /team/
          |-- page-mortimer.php
          |-- page-biff.php


As we see, the two filters can (and perhaps should) be used together, but can also be used alone.

Timber

As mentioned before, I use something like this on every project. I generally put all my templates into a directory called "controllers" and my twig files (if using Timber) into a directory called "views" so I have something akin to an MVC application.

My functions file sets Timber to look for twig files in a directory called "views" which is right inside the theme directory (next to "templates"):

$timber = new \Timber\Timber();
Timber::$dirname = array('views');

so my templates/index.php could set up my Timber context and pass it all the way to the index.twig file in the "views" directory:

$context = Timber::get_context();
$context['posts'] = Timber::get_posts();
Timber::render('index.twig', $context);

Attachments (1)

template.diff (3.1 KB) - added by kylejennings83 2 years ago.
a diff of the wp-includes/template.php

Download all attachments as: .zip

Change History (9)

@kylejennings83
2 years ago

a diff of the wp-includes/template.php

#1 @dingo_bastard
2 years ago

Did you read the documentation? Especially this part: File organization of page templates

As discussed in Theme Files Organization WordPress recognizes the subfolder page-templates. Therefore, it’s a good idea to store your global page templates in this folder to help keep them organized.

Also I recommend this article from Tom McFarlin WordPress and MVC.

#3 @kylejennings83
2 years ago

@dingo_bastard Yes I know about the subdirectory for page-templates, but isn't that JUST for page templates, ie creating a page and selecting a special template for it?

My solution allows a clean up of everything. Another example I could have pointed out was using various filters to get all CPT templates (archive, single, ect ect) into a folder for that CPT. For example, say you have a CPT called "movies". By using:

<?php
add_filter('single_templates_path', 'move_movies_single_path');
add_filter('archive_templates_path', 'move_movies_archive_path');

You could group all those related files together into a directory called "movies". Now imagine that all your news/ blog posts were in a news folder, each section of pages had their own directory, ect ect. Your theme would be so clean and easy to navigate.

And thanks for the read, I guess I should change what I wrote but I just meant this would give people OPTION to organize their files into a MVC architecture. So in my case, I usually just separate my logic and presentation with Timber. So to expand on all these examples (but just moving/organizing the templates is enough ), youre theme directory could look like this:

/twentyseventeen/
|-- /assets/
|-- /inc/
|-- /templates/
    |-- index.php
    |-- single.php
    |-- /team/
         |-- page-mortimer.php
         |-- page-biff.php
         |-- page-kyle.php
    |-- /news/
        |-- single.php
        |-- single-posts.php
    |-- /articles/
        |-- archive-aritcles.php
        |-- single-articles.php
    |-- /movies/
        |-- archive-movies.php
        |-- single-movies-kung-fury.php
        |-- single-movies-water-world.php
        |-- single-movies-pacific-rim.php
        |-- taxonomy-movie-genres-scifi.php
        |-- taxonomy-movie-genres-comedies.php
        |-- taxonomy-movie-genres-indie.php
|-- /views/
    |-- index.twig
    |-- /team/
        |-- page-moritmer.twig
        |-- page-team-member.twig (used for all files in /template/team/)
|-- functions.php
|-- index.php
|-- README.txt
|-- rtl.css
|-- screenshot.png
|-- style.css

@SergeyBiryukov Thanks! I'm reading these tickets now, maybe we can merge things. This ticket is a bit different because it follows the patterns set by #14310. I'll comment in those tickets tho to see if anyone is interested in this one.

#4 @dingo_bastard
2 years ago

For putting CPT's into theme, that's not really a good idea imo. Imagine that you are developing a product for a client. You create a theme, and all the custom stuff is in the theme you created. Some time passes and the client now has a new contractor, who decides to change the theme completely. Imagine the horror of extracting all that content you bundled in with the theme.

My rule of thumb is - if you need to create a CPT, put it in a plugin. You can add custom templates from within the plugin with really not much hassle: adding page templates inside a plugin.

WordPress isn't meant to be a MVC application, so I really see no reason for forcing that on it.

But by all means, if you think that is something that would be useful, submit a patch. I guess it doesn't hurt to have an extra filter around :D

#5 @jarednova
2 years ago

@dingo_bastard I second @kylejennings83 suggestions and hope you'll consider his patch. I totally understand your recommendation about handling CPTs in a plugin. My experience with clients is actually the opposite though — they want everything in one clean place (the theme directory) that represents the architecture and style for the site. In a plugins directory, there's often confusion about what "should" be activated (especially after an over-excited intern goes through and installs a hundred plugins). Regardless, we can all argue convincingly why you'd be (crazy/correct) to put things like that in a (plugin/theme) depending on the situation.

Something I've always loved about WordPress is there's no "right way" to use it — yes people have built blogs, but they've also built movie rating sites, cooking sites, (I think even the first versions of OpenTable were built on a hacked-together WP install?) That's why 25% of the internet is powered by it.

I wish this same openness applied to architecture. While WP wasn't designed to be MVC in 2003; it *is* an MVC app. How do I know? Tens of thousands of devs use it as an MVC app every day! (through Timber and others like it). I hope the Core team will consider this (and patches) like that to make it more conducive to MVC-style development

Last edited 2 years ago by jarednova (previous) (diff)

#6 @dingo_bastard
2 years ago

  • Keywords has-patch needs-testing 2nd-opinion added

I disagree with you that it is an MVC app. It is partly that, with REST API being in the core, so that you can decouple front end view part, but it doesn't follow MVC pattern.

Not only that, but you cannot separate it in a subfolder - bedrock tries to do just that, but try to install a multisite and it just won't work (I know because I tried for several days to make it happen).

Making it fully MVC compliant would mean rewriting almost everything, and that just won't happen (backward compatibility + just the sheer amount of work that would need to be done in order to make it happen).

Just to be clear, I have nothing against this patch, if it's tested and if it helps with the development I'm all for it ;)

#7 @kylejennings83
2 years ago

@dingo_bastard

Just to be clear, this proposed change does not in anyway force anyone to adopt a MVC architecture, nor does it encourage or force putting CPTs in the theme. It merely allows moving the location of the template files to meet a developers needs.

I only used these MVC examples because I personally prefer the clean organization and separation of concerns that MVC offers.

Being able to move the templates opens up a whole new world for developers.

@dingo_bastard @jarednova @ikraav
Also - Are we in favor of closing this ticket and driving attention to https://core.trac.wordpress.org/ticket/13239

I have proposed my version of the filter change there and that ticket has something like 6 years (lol) of comments.

This ticket was mentioned in Slack in #meta by kjennings. View the logs.


16 months ago

Note: See TracTickets for help on using tickets.