Opened 9 months ago
Last modified 7 weeks ago
#21676 new enhancement
Pass a variable to get_template_part()
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | Awaiting Review |
| Component: | Template | Version: | 3.4.1 |
| Severity: | normal | Keywords: | has-patch close |
| Cc: | knut@…, xoodrew@…, geertdd@…, contact@…, giulio.mainardi@…, johnzanussi, ian_dunn@…, lol@… |
Description
Having the ability to pass a variable into get_template_part would be invaluable, it would really clean up the issues with using globals and to further cement it's use rather than the alternative of a normal PHP include/require.
It would be the third variable passed into get_template_part, which I could pass it a string, array, object, or whatever I want really. Here's an example of passing all the current scope's variables:
<?php get_template_part( 'twitter', 'feed', compact( array_keys( get_defined_vars() ) ) ); ?>
and then catching them in my feed-twitter.php file:
if ( !empty( $_data ) && is_array( $_data ) ) extract( $_data, EXTR_SKIP );
I can pass other things in, but that's a really valuable example in my uses for this new variable.
Attachments (4)
Change History (30)
sc0ttkclark — 9 months ago
comment:1
sc0ttkclark — 9 months ago
+1. Currently, you're forced to implement your own version of load_template() if you want to pass additional variables, without polluting the global namespace.
comment:4
sc0ttkclark — 9 months ago
- Type changed from feature request to enhancement
comment:5
sc0ttkclark — 9 months ago
- Keywords has-patch dev-feedback added
comment:6
DrewAPicture — 9 months ago
- Cc xoodrew@… added
comment:7
sc0ttkclark — 8 months ago
For devs -- should I update the patch to switch get_template_part to accept $args wp_parse_args with the new '_data' variable?
- Keywords needs-testing added; dev-feedback removed
- Milestone changed from Awaiting Review to 3.5
For anyone else confused by that question, it was in reference to this:
http://core.trac.wordpress.org/ticket/21673#comment:4
As Mike said, adding one extra parameter to get_template_part() is fine.
But checking if the $slug is an array and then treating the whole function as having associative args would be really confusing.
In conclusion, the patch looks fine. Let's try to land it in 3.5.
comment:9
sc0ttkclark — 8 months ago
Sounds great! Thanks for the review and feedback, just wanted to be sure I did everything expected / wanted of me for this ticket and for future-proofing things.
comment:10
nacin — 8 months ago
- Milestone changed from 3.5 to Future Release
I am not a fan of this.
$_data should always be an array and should be extracted. It should be for passing variables, not arbitrary data.
Globals and query variables should not be extracted, as they are now. It's confusing and lame. That means this should not be get_template_part(), and it should instead be something like wp_load_template() (similar to the old bb_load_template()).
This would essentially be a new utility function, a clean break from everything else. get_template_part() is designed for template modularization and child theme inheritance, let's not complicate it further.
comment:11
wonderboymusic — 8 months ago
Want a dirty workaround?
function get_template_part_data() {
$func = wp_list_filter( debug_backtrace(), array( 'function' => 'get_template_part' ) );
if ( $func )
return $func[key($func)]['args'][2];
}
$data = array( 'foo' => 'bar' );
get_template_part( 'content', 'whatever', $data );
exit();
And then in content-whatever.php:
print_r( get_template_part_data() );
comment:12
scribu — 8 months ago
I think nacin's implicit objection is this:
Adding a $data parameter to get_template_part() is wrong because it mixes two ways of "templating":
1) The "WordPress" way, where you call the_title(), the_content() etc. + globals like $wp_query.
2) The "bare-bones" way, where you pass an array of data, which gets converted into some variables:
function wp_load_template( $path, $data ) {
extract( $data );
include $path;
}
@wonderboymusic: Do you chat with your mother using those fingers? :P
comment:13
wonderboymusic — 8 months ago
Nacin just Skype'd me his disgust as well. I made sure the word "dirty" was in there! but +1 for using wp_list_filter, no?
comment:14
sc0ttkclark — 8 months ago
The end goal of this ticket, is to provide a way to pass data and additional context into a template file, that's child/parent theme aware, and includes that file.
get_template_part does part of that, the proposed wp_load_template would do part of that, why not go all the way or at the very least offer another function that does handle child/parent theming?
comment:15
sc0ttkclark — 8 months ago
- Keywords dev-feedback 2nd-opinion added
I went ahead and refreshed the patch with extract / array usage as discussed with @scribu
I think we should have another dev hop in on this conversation, it seems like including a file with get_template_part or load_template and having the ability to scope variables in, is something that people work around with dirty global variables.
It would seem like this would improve usage of core theming functions like these as opposed to include/require.
Even with @wonderboymusic's idea, that could work as a work-around, but then everyone has to add that function and it'll be another thing every themer bakes differently.
The inclusion of this patch seems rudimentary, it holds great value, and I'd like to open this discussion up to any core developer or theme developer who may have other points to make.
comment:16
GeertDD — 4 months ago
- Cc geertdd@… added
I definitely do like the proposed functionality. Being able to pass on data to a template allows you to separate your markup from your logic. It would work much like a View (as in MVC).
comment:17
stephenh1988 — 4 months ago
- Cc contact@… added
comment:18
beatpanda — 4 months ago
This comes up a lot in my work, and some of my plugins and themes would be drastically better if this was core functionality. Right now I'm having to implement my own version of WordPress core functions to do this.
I know this isn't likely to happen, but if the $data array used the EXTR_OVERWRITE option instead of EXTR_SKIP, that would be extremely helpful, because then I could pass in a custom set of posts to a template as $posts or $post in the $data array and the template would still "just work".
I came here to submit roughly this exact patch, which is roughly what my hacky implementation looks like. Please implement this.
sc0ttkclark — 4 months ago
Refreshed, using $args instead of $data for future-proofing additional functionality
comment:19
sc0ttkclark — 4 months ago
Just attached a new patch which proposes a slightly different and more future-proof approach. It uses an $args array, to provide the ability to add additional features later on down the road, instead of merely adding another $var to the parameters list.
As part of the new $args array, if you set $args[ 'data' ] to an array of 'key' => 'value', then it will extract() that (like the previous patches).
comment:20
sc0ttkclark — 4 months ago
Also, in my refreshed patch, $args[ 'data' ] is now extracted above $wp_query->query_vars so you can easily override any of those.
For overriding globals as set in load_template, the best way there is to interact with the globals themselves like $GLOBALS[ 'posts' ] etc
comment:21
giuliom — 4 months ago
- Cc giulio.mainardi@… added
comment:22
johnzanussi — 4 months ago
- Cc johnzanussi added
comment:23
iandunn — 3 months ago
- Cc ian_dunn@… added
comment:24
wonderboymusic — 3 months ago
- Keywords close added; needs-testing dev-feedback 2nd-opinion removed
- Milestone changed from Future Release to Awaiting Review
I think passing $data or $args down the chain is worse than importing globals. load_template() imports a bunch of globals, that's how function scope in PHP works. Is it better to import those variables using an argument to load_template()? That's not even the question being asked, the question is how to jam more data in there, and the answer is simple: import those globals in your function. If you hate global scope, limit your app's global pollution to one object - for instance, I use an $emusic global variable (stdClass), and I have a get_emusic() function to retrieve it, so I import zero globals, yet always have access to them:
function where_are_my_vars() {
$vars = get_emusic()->right_here;
}
Suggesting close / wontfix
comment:25
sc0ttkclark — 3 months ago
- Cc lol@… added
The idea behind this patch was to give get_template_part the ability to work more like a normal include/require works, passing variables from the current scope (or whatever is wanted) directly to the new scope of load_template()
Using globals and doing the custom code for each template was something I explicitly set out not to have to do for every single template. There's just no other cleaner way that I can see to bring variables in scope (without making them globals) with the template being included.
Passing $args to get_template_part also opens things up to further patches that could also enhance how it works and functions.
comment:26
ocean90 — 7 weeks ago
#23924 was marked as a duplicate.

This is a ticket split off of #21673 to make it more viable for inclusion.