WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#16128 closed feature request (worksforme)

WordPress Template System Override

Reported by: pearsonified Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.1
Component: Themes Keywords: has-patch 2nd-opinion close
Focuses: Cc:

Description

As it's currently constructed (in version 3.0.4), the WordPress template loader (wp-includes/template-loader.php) is relatively inflexible. No matter how a theme operates, it's forced through the series of if-statements and template "fetches" defined in lines 23–41 of template-loader.php.

Fortunately, by making very simple modifications to this file, we can accommodate themes/frameworks/template systems that may have different (and, ideally, more efficient) ways of determining which template to show and how to show it.

This is sensible because developers only need the contents of $wp_query in order to determine which template to show. While the current workings of the WP template system include a lot of "convenience" functions, these unnecessary function calls could be skipped entirely by relying upon the $wp_query->is_[x] variables.

My proposal for a template system override is quite simple, and it introduces one new constant and one new hook into the core. The constant, WP_THEME_TEMPLATE, is a boolean value that theme developers should place in their functions.php file and set to TRUE only if they have defined their own template system. The hook, theme_template, is the "tie-in" point for the developer's template system.

The template-loader.php file must be modified to accommodate the constant and hook described above. Fortunately, this can be done in 4 lines of code, as evidenced by (new) lines 22–24 and line 48 in the attached template-loader.php file.

I like this template system solution because it does not affect any current themes, developers, or development practices. Despite this, it opens to door to innovation and places the dev community in a position to come up with mind-blowing new ways to handle template/theme functionality.

Attachments (2)

template-loader.php (2.0 KB) - added by pearsonified 3 years ago.
template-loader.php.diff (3.2 KB) - added by nathanrice 3 years ago.

Download all attachments as: .zip

Change History (18)

pearsonified3 years ago

comment:1 dd323 years ago

  • Keywords has-patch 2nd-opinion added; themes templates removed
  • Milestone changed from Awaiting Review to Future Release
  • Type changed from enhancement to feature request

Similar requests have been asked before; so i'm marking this as Future Release; 2nd-opinion.

comment:2 nathanrice3 years ago

I like the idea ... theme authors really should have a little more control in the template loading arena, if for no other reason than to extend (rather than replace) the current system.

However, instead of using a constant, let's take advantage of the theme support functionality. Adding theme-specific functionality is a perfect use for those functions.

In my patch, the code checks to see if the theme supports 'theme-templates'. Probably needs a better naming scheme, but this one will do for testing purposes, and can be renamed later. All that needs to be done to activate custom theme templating is to add the following to a theme's functions.php file:

add_theme_support('theme-templates');

Patch attached ...

Last edited 3 years ago by nathanrice (previous) (diff)

comment:3 follow-up: duck_3 years ago

Why can't template_redirect be used for this?

comment:4 in reply to: ↑ 3 ; follow-up: nathanrice3 years ago

Replying to duck_:

Why can't template_redirect be used for this?

The idea is to circumvent the standard template loader. I'm not sure where template_redirect fires (either before or after the template loader runs) but the idea is to stop the standard template loader from running if there is an alternate loader present.

comment:5 nathanrice3 years ago

  • Cc nathanrice added

comment:6 in reply to: ↑ 4 greuben3 years ago

Replying to nathanrice:

Replying to duck_:

Why can't template_redirect be used for this?

The idea is to circumvent the standard template loader. I'm not sure where template_redirect fires (either before or after the template loader runs) but the idea is to stop the standard template loader from running if there is an alternate loader present.

Current theme supports? constants? Sounds scary to me.

Okay let's say if you have used current_theme_supports 'theme-templates' or 'WP_THEME_TEMPLATE', what do you do with the action theme_template? check for same is_* and load files with different name??

You can either use 'template_redirect' or 'template_include' action to load whatever template you want.

Or did I get you wrong?

comment:7 follow-up: nacin3 years ago

  • Keywords close added

Small picture: There's no need to keep an action under lock and key unless a theme supports it.

Big picture: template_redirect is the *perfect* hook here. It's designed to be used to include a template and die. If you want to override the template hierarchy entirely, then you already have this power.

comment:8 in reply to: ↑ 7 ; follow-up: pearsonified3 years ago

Nacin, the problem with not changing anything is that you cannot prevent the rest of the template-loader.php file from running, as Nathan mentioned in his response to duck_ above.

Any thoughts on that end of things?

comment:9 in reply to: ↑ 8 ; follow-up: duck_3 years ago

Replying to pearsonified:

Nacin, the problem with not changing anything is that you cannot prevent the rest of the template-loader.php file from running, as Nathan mentioned in his response to duck_ above.

Any thoughts on that end of things?

"include a template and die"

untested:

add_action( 'template_redirect', 'this_is_a_silly_example' );
function this_is_a_silly_example() {
    if ( is_single() ) {
        include( TEMPLATEPATH . '/path/to/my/template.php' );
        exit;
    }
}

comment:10 in reply to: ↑ 9 ; follow-up: pearsonified3 years ago

Replying to duck_:

Replying to pearsonified:

Nacin, the problem with not changing anything is that you cannot prevent the rest of the template-loader.php file from running, as Nathan mentioned in his response to duck_ above.

Any thoughts on that end of things?

"include a template and die"

untested:

add_action( 'template_redirect', 'this_is_a_silly_example' );
function this_is_a_silly_example() {
    if ( is_single() ) {
        include( TEMPLATEPATH . '/path/to/my/template.php' );
        exit;
    }
}

IMO, exits and breaks (except when used in switch statements) are not elegant, and generally speaking, you can find ways to write workable code without the need to force anything in this manner.

comment:11 in reply to: ↑ 10 pearsonified3 years ago

Replying to pearsonified:

Replying to duck_:

Replying to pearsonified:

Nacin, the problem with not changing anything is that you cannot prevent the rest of the template-loader.php file from running, as Nathan mentioned in his response to duck_ above.

Any thoughts on that end of things?

"include a template and die"

untested:

add_action( 'template_redirect', 'this_is_a_silly_example' );
function this_is_a_silly_example() {
    if ( is_single() ) {
        include( TEMPLATEPATH . '/path/to/my/template.php' );
        exit;
    }
}

IMO, exits and breaks (except when used in switch statements) are not elegant, and generally speaking, you can find ways to write workable code without the need to force anything in this manner.

The theme_template proposal eliminates the need to do this, which is one of the (many) things that I find attractive about it.

comment:12 follow-up: nacin3 years ago

  • Milestone Future Release deleted
  • Resolution set to worksforme
  • Status changed from new to closed

Replying to pearsonified:

Nacin, the problem with not changing anything is that you cannot prevent the rest of the template-loader.php file from running, as Nathan mentioned in his response to duck_ above.

Any thoughts on that end of things?

Yep. I hinted to it in my last comment, but -- nothing else runs after template loader. So just exit or die when you're done to kill the script. Including the die is pretty standard whenever you need to use template_redirect to load a template, because whenever a plugin wants to override that, they'll need to stop the rest of the template hierarchy from firing. This is standard practice in plugins, and it really isn't that inelegant at all. Again, nothing else ever fires after the template loader -- imagine a die() at the end of the file already. You're just short-circuiting it.

Make sense? I better understand the problem and use case that you and Nathan laid out, and I'm confident this is the exact hook you're looking for, so I'm closing this as worksforme.

Cheers :-)

comment:13 in reply to: ↑ 12 pearsonified3 years ago

Replying to nacin:

Replying to pearsonified:

Nacin, the problem with not changing anything is that you cannot prevent the rest of the template-loader.php file from running, as Nathan mentioned in his response to duck_ above.

Any thoughts on that end of things?

Yep. I hinted to it in my last comment, but -- nothing else runs after template loader. So just exit or die when you're done to kill the script. Including the die is pretty standard whenever you need to use template_redirect to load a template, because whenever a plugin wants to override that, they'll need to stop the rest of the template hierarchy from firing. This is standard practice in plugins, and it really isn't that inelegant at all. Again, nothing else ever fires after the template loader -- imagine a die() at the end of the file already. You're just short-circuiting it.

Make sense? I better understand the problem and use case that you and Nathan laid out, and I'm confident this is the exact hook you're looking for, so I'm closing this as worksforme.

Cheers :-)

Andrew, thanks for the response!

I suppose the bigger question here is this: The template system is designed to work one specific way, but it can be hax0red to work differently with the template_redirect hook. Instead of requiring a hook for modification, why not treat all template systems the exact same by firing them at one, consistent time? If the developer chooses which system to show, I don't see why this would be a problem for anyone.

From a more general standpoint, I'm suggesting that any template system should be considered to be of type X, regardless of whether it's the standard WP template system or a new one that no one has built yet. However, under the current (unchanged) construct, you have two template system types: X and Y, where Y is any template type that is fired from the template_redirect hook.

The coder in me sincerely wants to consolidate these different types into one, unified structure. IMO, it's the right thing to do.

comment:14 follow-ups: scribu3 years ago

Agree with closing. The current system for short-circuiting the default template loader is pretty neat IMO.

The only problem is that template_redirect is also used for other things, which should run before die().

The posts_selection action should be advertised more.

comment:15 in reply to: ↑ 14 nathanrice3 years ago

Replying to nacin:

Yep. I hinted to it in my last comment, but -- nothing else runs after template loader. So just exit or die when you're done to kill the script.

I see what you mean. I didn't realize the template loader was the last (I mean LAST) thing to run.

comment:16 in reply to: ↑ 14 nathanrice3 years ago

Replying to scribu:

The only problem is that template_redirect is also used for other things, which should run before die().

If you hook to template_redirect and need it to be the LAST thing to execute, you're right. Lots of plugins use that hook. I guess using a 100 priority is safe enough :-)

Note: See TracTickets for help on using tickets.