#19063 closed enhancement (wontfix)
Custom post_types and get_template_part
Reported by: | impleri | Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | minor | Version: | |
Component: | Template | Keywords: | has-patch |
Focuses: | Cc: |
Description
Can we modify the get_template_part process to allow custom post_type and custom taxonomy from plugins? I'm pretty sure I'm not the only person who uses custom post_types and would like to see an easier way to add a default template file without encroaching upon existing theme files, adding child themes, or requiring themes which are explicitly compatible with the particular post_type.
I've included a patch which is based on my current approach in using the archive_template, single_template, etc filter.
Attachments (6)
Change History (24)
#2
@
13 years ago
How can you be sure that $slug in "$slug-$type.php"
isn't 'page' or 'archive' or some other string that will load a wholly unexpected template file?
#3
@
13 years ago
Is that really necessary? If a template author creates a template file of archive-magical_mystery_type.php
and loads get_template_part('archive')
on a post with magical_mystery_type.php
, why should this assume the template file in question doesn't handle magical_mystery_type
less than archive.php
does? One would think that if a template author goes out of her way to create an archive page for a custom post_type, that file will work for that custom post_type better than the plugin author's default.
Further, all of this still employs WordPress's own process and template logic (e.g. locate_template
) with the single addition of allowing plugin authors a last-stop attempt at outputting their templates without using get_content, template_redirect, or template_include -- each which again make it difficult to adjust for different themes (in their own peculiar way).
#4
@
13 years ago
I couldn't apply your patch.
Please make patches relative to the root WP dir. More importantly, please make them against the current trunk.
#5
@
13 years ago
I was able to apply new.2.diff and noticed that it doesn't account for when:
get_query_var('post_type')
returns false (default)
get_query_var('post_type')
returns an array of post types
Also, I don't think get_template_part() is the right place for adding this. It should remain a generic function, similar to locate_template().
PS: Please leave a comment when you upload a new patch, as they don't trigger a notification.
#6
@
13 years ago
Finally, please provide some examples as to which template you think should load for which URL.
#7
@
13 years ago
If post_type
is false, the if(!in_array($post_type, $default_types))
will return false, thereby ignoring the additional template possibilities (after all, the interest is for custom post_types -- which will have post_type
set).
For the array, this should be changed to retrieve the post_type for the actual post (easy enough) which cannot be an array (at least according to the DB design). Would using get_post_type()
fix this? (posting new patch with this)
I disagree on using something like locate_template()
for a few reasons. First, it comes too late in the template loading process. Adjusting get_template_part()
as I propose is essentially the same as adjusting locate_template()
except in one crucial point, which is my second reason: it would add additional filtering and process time because locate_template()
is called for every template piece. Using something like get_template_part()
follows what I think are the goals in the template system: modularity. Using locate_template()
, while it does this as well, it adds process time without benefit. Thirdly, get_template_part()
appears to be the logical choice because that is where possible template names are decided. Pushing this to locate_template()
would be obfuscating its function. The options as I see them are to use get_template_part()
or to create a new function similar to get_header()
(e.g. get_main_content()
or something) though even then get_template_part()
would need to be modified to allow for a base plugin-defined template (either by postponing load_template()
until after a filter check -- like I have done -- or returning a template path to a get_main_content()
function which then does load_template()
after a filter check).
Since this is meant to enable custom post_types to display properly, a URL like http://mysite.com/records/my-own-musical-beast/
which is used by a music record/album custom post_type might not display anything because the content is a listing of songs generated from the DB. Currently, I would need to filter the_content
in order to display this, filter on template_include
or single_template
to redirect to a template which will show the correct data. In the first case, I am hardcoding the template from my plugin (not good). In the latter two cases, I am overriding the actual template (e.g. what if a template puts the sidebar on the left but does not do so in the template's header.php like TwentyEleven does in footer.php?). By using get_template_part()
or something similar, it is easier for my record file to show in a randomly-given theme without forcing a particular template layout. For example, I'm updating the extinct Now Reading plugins to use custom post_types. A book (e.g. http://beta.impleri.net/library/product/the-girl-with-the-dragon-tattoo/ ) needs to be able to have multiple authors, an image, a link to Amazon page, etc. These do not show up on the template pages because, obviously, they are custom data which need to be displayed. What I'm doing right now is using the single_template
filter, checking if the custom single-ml_product.php
file was found by locate_template()
and, if not, redirecting to the single-ml_product.php
template file in my plugin directory. This is not a good solution because I've had to copy the entire page layout from TwentyEleven (I'll attach this file as well) which may not work with other templates. I could have filtered the_content
but then I am requiring a hardcoded style across which makes it more difficult to users to have template-specific designs. If I could have filtered through get_template_part()
, users would only have to worry about minor tweaks for a template which they could put in their template folder without needing to recreate a loop page -- much like TwentyEleven has made it possible with its content-single.php
file. Thus far, that seems to be simplest solution which is most extensible and most logical from what I can tell.
#8
follow-up:
↓ 10
@
13 years ago
Please try not to post big walls of text; it's hard to follow.
I was hoping for a few short examples, in the form of: "When loading URL X, with line of code Y, I can load template Z."
I disagree on using something like locate_template() for a few reasons.
I wasn't suggesting going lower down the stack, but higher i.e. to get_archive_template() etc. as you later suggest.
#9
@
13 years ago
This is not a good solution because I've had to copy the entire page layout from TwentyEleven
I attempt to tackle that with Theme Wrappers, but it's something that theme authors must adopt.
#10
in reply to:
↑ 8
@
13 years ago
Please try not to post big walls of text; it's hard to follow.
Apologies. I write/talk a lot (12+ years of uni does that!)
I was hoping for a few short examples, in the form of: "When loading URL X, with line of code Y, I can load template Z."
Which is why I provided a URL to an actual example I am working with. The URL is for a custom post_type (ml_product) which has its own custom metadata (book information). Since it is a CPT, most of its code is standard WP handling. However, the template needs to display the book metadata (authors, cover image, publication date, whatever). I currently hack the entire template through the archive_template
filter.
I wasn't suggesting going lower down the stack, but higher i.e. to get_archive_template() etc. as you later suggest.
Wouldn't going higher make it harder for template authors to provide their own template? Also, using get_*_template()
is already possible (through the *_template
filter called in get_query_template()
). It still requires plugins to output the entire template instead of the small portion which they are adapting (i.e. #div > #content
). get_template_part()
can handle that exact section.
I attempt to tackle that with Theme Wrappers, but it's something that theme authors must adopt.
I agree that everything should be reduced to a single wrapper, but I don't see how Theme Wrappers does it any differently from get_template_part()
. In fact, what differences are there in archive.php
and single.php
which cannot be resolved by using get_template_part()
or abstracting them into loop-archive.php
and loop-single.php
to complement the content-archive.php
and content-single.php
files?
#11
@
13 years ago
So, how could a plugin use the 'get_custom_template_part' filter generically, without knowing anything about the theme? Code please.
#12
@
13 years ago
Easy enough since I already had it planned. Here's the hook for a plugin. It has less dependence on a specific theme, though it's not completely independent. It's perhaps impossible to do this for every theme, but it at least makes it more compatible (and less wasted recycling of layout) with themes.
#15
follow-up:
↓ 17
@
11 years ago
- Keywords 2nd-opinion removed
- Resolution set to wontfix
- Status changed from new to closed
get_template_part()
Is meant to be a simple tempting function that gets a template part. This complicates our template hierarchy. Couldn't you do basically the same thing in your archive.php file? Put your function that returns the $slug-$type part then in your archive.php
$template = your_slug_type_function(); get_template_part( $template. '-loop' );
#17
in reply to:
↑ 15
@
11 years ago
Replying to c3mdigital:
get_template_part()
Is meant to be a simple tempting function that gets a template part. This complicates our template hierarchy. Couldn't you do basically the same thing in your archive.php file? Put your function that returns the $slug-$type part then in your archive.php
That's fine for theming stuff, but I'm coming at it from the perspective of a plugin author. I have a plugin which uses CPT to display books. For someone to be able to use my plugin, they cannot simple install it. They have to either edit their template files (as you suggest) or create their own template files. So, are you suggesting that I, as a plugin author, create a theme template and require users to use it or roll their own just so that my CPT is actually viewable?
This kind of leaving third party developers out to dry is a reason why I've slowly left using WP. Both Joomla and Drupal have this kind of functionality out of the box. Sad, because I'd rather use WP than the others or forking WP for such a small change. All I'm asking is for post types to be included in the get_post_template() magic and an additional WP hook to allow plugins to define initial template parts for those CPT.
first attempt