WordPress.org

Make WordPress Core

Opened 4 years ago

Closed 19 months ago

Last modified 19 months ago

#31475 closed enhancement (invalid)

Add ability to change the folder location for templates

Reported by: rugbert Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.1
Component: Themes Keywords:
Focuses: Cc:

Description

I've seen questions here and there on stack exchange asking how to change the location WP looks for templates and I have wanted to do this for a long time, and as it stands now, it is not possible to change the location of the WP templates without changing wp core. But I've gone ahead and worked something out.

First tho, why should this be change? I see 3 good reasons.

  1. It allows developers set up a folder structure which more closely resembles a MVC framework which is, by definition, more organized and cleaner than what wordpress expects.
  2. It complements the Timber plugin
  3. Because it's easy to impliment and can be 100% optional for developers

Here's how I did it:
In your theme's function.php (or in wp-config.php) we create a constant called something like "WP_TEMPLATE_DIR" and setting the value to the name of the desired directory.

define('WP_TEMPLATE_DIR', 'controllers');

Then the location_template function needs to be modified, see below

Note - I cant highlight the changes due to code block formatting, but essentially we:

  1. Set a variable called $path to an empty string
  2. Check to see if the constant is defined and the specified folder exists. If it does we set the $path variable to the specified folder
  3. we simply inject the $path variable into the TEMPLATEPATH . '/' . $template_name; So if the constant is not set, path will just be an empty string and therefore the path location will not change.
function locate_template($template_names, $load = false, $require_once = true ) {
	$located = '';
	foreach ( (array) $template_names as $template_name ) {
		if ( !$template_name )
			continue;

        $path = '';
        if( defined('WP_TEMPLATE_DIRECTORY')
            && ( !empty(WP_TEMPLATE_DIRECTORY) && !is_null(WP_TEMPLATE_DIRECTORY))
            && file_exists( STYLESHEETPATH . '/' . WP_TEMPLATE_DIRECTORY)  ){

            $path = WP_TEMPLATE_DIRECTORY. '/';
        }

        if ( file_exists(STYLESHEETPATH . '/' . $path . $template_name)) {
			$located = STYLESHEETPATH . '/' . $path . $template_name;
			break;
		} else if ( file_exists(TEMPLATEPATH . '/' . $path . $template_name) ) {
			$located = TEMPLATEPATH . '/' . $path . $template_name;
			break;
		}
	}

	if ( $load && '' != $located )
		load_template( $located, $require_once );

	return $located;
}

So wordpress is now looking for templates in the "controllers" folder that is located in the root of my theme. Now when I set up timber, I can have a folder called "views" for the twig tempalates, next to a folder called "controllers" for my actual wordpress templates and then I could set up my custom post types/taxonomies/whatever in a folder called models.

Now my theme folder only has functions.php, style.css, and then some folders to organize everything.

Change History (7)

#1 @SergeyBiryukov
4 years ago

Related:

#12877
Modular themes: Apply template hierarchy to folders within a theme
#13239
Filter locate_template template_names variable
#22355
Template stack - Beyond parent/child theme relationships


#2 in reply to: ↑ description @rugbert
4 years ago

Corrected some code (it doesn't look like we can edit our posts here)

Moved the constant path check conditional out of the loop, and fixed a fata error in the same conditional.

function locate_template($template_names, $load = false, $require_once = true ) {
	$located = '';
        $path = '';
        if( defined('WP_TEMPLATE_DIRECTORY')
            && !is_null(WP_TEMPLATE_DIRECTORY)
            && file_exists( STYLESHEETPATH . '/' . WP_TEMPLATE_DIRECTORY)  ){

            $path = WP_TEMPLATE_DIRECTORY. '/';
        }

	foreach ( (array) $template_names as $template_name ) {
		if ( !$template_name )
			continue;

                if ( file_exists(STYLESHEETPATH . '/' . $path . $template_name)) {
			$located = STYLESHEETPATH . '/' . $path . $template_name;
			break;
		} else if ( file_exists(TEMPLATEPATH . '/' . $path . $template_name) ) {
			$located = TEMPLATEPATH . '/' . $path . $template_name;
			break;
		}
	}

	if ( $load && '' != $located )
		load_template( $located, $require_once );

	return $located;
}

#3 follow-up: @lkraav
4 years ago

I need to switch template directories mid-request to a plugin, once I've identified that the request handling belongs to the plugin. In this case, action "wp" is safe, which is pretty late. Since it's based on constants, it doesn't look like @rugbert's patch would allow me to do this.

#4 in reply to: ↑ 3 ; follow-up: @rugbert
3 years ago

Replying to lkraav:

I need to switch template directories mid-request to a plugin, once I've identified that the request handling belongs to the plugin. In this case, action "wp" is safe, which is pretty late. Since it's based on constants, it doesn't look like @rugbert's patch would allow me to do this.

Hey @ikraav, sorry for the late reply. Can you give ma little bit more information about what you're doing?

I guess you have a hook that listens for requests and determines which template needs to be loaded and then passed it off to a plugin if applicable? Whats the plugin called?

I've been working on a plugin version of this ticket to workout bugs and add features and would love to solve this problem as well.

Thanks!

#5 in reply to: ↑ 4 @lkraav
3 years ago

Replying to rugbert:

Hey @ikraav, sorry for the late reply. Can you give ma little bit more information about what you're doing?

Heya. Take a look at what we ended up with at https://github.com/justintadlock/hybrid-core/issues/111

#6 @rugbert
19 months ago

  • Resolution set to invalid
  • Status changed from new to closed

#7 @netweb
19 months ago

  • Milestone Awaiting Review deleted
Note: See TracTickets for help on using tickets.