#13818 closed task (blessed) (fixed)
There should be index pages for custom post types
Reported by: | frankieroberto | Owned by: | nacin |
---|---|---|---|
Milestone: | 3.1 | Priority: | normal |
Severity: | normal | Version: | 3.0 |
Component: | Template | Keywords: | has-patch |
Focuses: | Cc: |
Description
Currently, if you create a custom post type, and have rewrites enabled, it will generate posts with URLs along the lines of /post-type/post-name. However, if you try to access an index page at the obvious URL of /post-type you'll get a 404, as Wordpress will try to find a page with that slug.
Whilst it's possible to manually create a page with that slug name, and then use a custom template to generate a query bringing back the most recent posts with a set post-type, it'd be useful if this was built-in (and I suspect it'd be the expected behaviour).
Suggested function to use would be is_post_type() which uses the template post-type-slug.php falling back to archive.php if that's not present.
Attachments (2)
Change History (77)
#1
@
14 years ago
- Cc yeswework added
- Component changed from General to Template
- Milestone changed from Unassigned to 3.0
- Priority changed from normal to high
- Version set to 3.0
#3
@
14 years ago
- Milestone set to Future Release
We have already decided not to deal with this for 3.0, and watch how people will utilize custom post types first. There is a big-picture rationale here.
Please note, category.php only works when the rewrite rules direct you to a specific category. It doesn't handle the /category base out of the box. We *do* have single-books.php which handles the singular instance, and we're leaving the archive listing up to a plugin (which is easier than what's going on in that tutorial).
#4
@
14 years ago
I can't think of many cases where a default template file for each custom post type wouldn't be either absolutely necessary or at least very useful (just as with taxonomies). The choice not to implement this seems both inconsistent and counterproductive.
On the point that there is nothing to handle '/category' out of the box, that's not really true, since the default query passed to index.php does precisely that.
And yes – category.php (and likewise taxonomy.php) works when the rewrite rules direct you to a specific category... which is precisely the functionality that's missing for custom post types! An equivalent template option, eg. 'types.php' (or whatever), with the rewrite rules set and right query information passed in, seems to me really important. I'm trying to build a site right now which uses these features, and the custom post types don't seem useful at all without this option.
You say that there's a 'big picture rationale', which I take to mean that you don't want to add a load of features that won't be useful. That's fair enough. But I think the lack of this feature will make it hard for people even to get started with custom post types. In that sense, your picture of 'how people will utilize custom post types' will be inherently skewed from the outset.
As you maybe saw in the article which I pasted, CMS Press is a plugin which gives you a GUI for custom post types and custom taxonomies (something we've been recommending elsewhere), but also, apparently, generates the extra rewrite and template rules to be able to use them out of the box in the way I'm describing. Great! The problem is, CMS Press stores its custom post type definitions independently of functions.php – so if you happen to have set up a site using the widely recommended functions.php method (as I have), then this plugin is no good. If you can recommend another that'll solve the template/redirect problem, let me know. Otherwise perhaps I'll just have to start again using this pseudo-core plugin...
#5
@
14 years ago
I disagree that functions.php is widely recommended. Many tutorials have suggested that for pure simplicity, but in reality, post types will often be part of a much larger plugin that can fully leverage them.
/category sends you to index.php with a 404 handler, same deal as /my-post-type.
Developers will use post types differently. And, yes, '"developers."' Custom post types are not for people copy-pasting code without really understanding what is going on. Custom post types are not for them.
Custom post types are plenty useful if you are aware of the APIs needed to leverage your specific needs.
#6
follow-up:
↓ 13
@
14 years ago
Of course, it's advanced-level stuff, and you have to understand what you are doing. And of course, it's new functionality and it will evolve over time.
All I'm saying is that, as developers working constantly on many different kinds of WP implementation, we're convinced that a very large proportion of uses of custom post types will want to make use of an automatically-populated, corresponding template (or part-template) for each type. To us this just seems like a no brainer: not least because the automatic distribution of relevant queries to template files, as already fully implemented with taxonomies, is one of WP's most helpful, nay indispensable, features. And as this very ticket (not submitted by me) and the blog post I quoted have already shown, the point about its absence for custom post types is already being raised online before release...
In any case, I defer to you the developers. At the very least, please keep it in mind going forward!
#7
@
14 years ago
Hi all,
Thanks for the comments.
I'd be interested to see any code that demonstrates how you can get /custom-post-type to display a custom index page template without having to do to much hacking on top of the rewrite functions.
In my opinion, adding this type of index page to the template hierarchy would be really useful for plugin developers using the custom post types API.
Oh, and I submitted a feature request for index pages for /category and /tag separately. See http://core.trac.wordpress.org/ticket/13816
#8
@
14 years ago
- Type changed from feature request to enhancement
I've just found this plugin, which adds most of the 'missing' functionality I've described here: http://wordpress.org/extend/plugins/simple-custom-post-type-archives/
I think the plugin is a good candidate for being incorporated into Core.
#11
@
14 years ago
Another Related Ticket: #12183
http://lists.automattic.com/pipermail/wp-hackers/2010-February/030333.html
#13
in reply to:
↑ 6
@
14 years ago
- Cc mikeschinkel@… added
Replying to nacin:
Developers will use post types differently. And, yes, '"developers."' Custom post types are not for people copy-pasting code without really understanding what is going on. Custom post types are not for them.
Does it really have to be that way? Custom post types are not just something developer can understand; people with real world use-cases can easily understand the value of custom post types.
Replying to yeswework:
All I'm saying is that, as developers working constantly on many different kinds of WP implementation, we're convinced that a very large proportion of uses of custom post types will want to make use of an automatically-populated, corresponding template (or part-template) for each type. To us this just seems like a no brainer: not least because the automatic distribution of relevant queries to template files, as already fully implemented with taxonomies, is one of WP's most helpful, nay indispensable, features.
+1
#15
@
14 years ago
- Cc jer@… added
Big +1 on this idea. I agree that it is a no-brainer to have it supported by default.
If someone doesn't want an archive like this then they should use a setting in their post type definition to do so, though it seems like maybe the 'private' flag would work. If its private, no index, otherwise do the routing people expect.
#16
@
14 years ago
Another big +1. I'm really surprised that this hasn't been implemented on the outset. The custom post type system feels incomplete without an archive/index page similar to category-slug.php:
http://codex.wordpress.org/images/1/18/Template_Hierarchy.png
Was pulling my hair out over this!. Now using this plugin:
http://www.cmurrayconsulting.com/software/wordpress-custom-post-type-archives/
but it feels hackish and doesn't fully work as expected (custom menu support etc, see comments)
Nacin, arguing against an index page feels like arguing against library catalogs.
#18
@
14 years ago
Very enthusiastic +1. All hair figuratively, but firmly, pulled from head.
@FrankieRoberto - something in the simple-custom-post-type-archives code is generating illegal offset errors when used in conjunction with a request filter for getting custom post types into author.php. Looking into it now.
#20
@
14 years ago
- Owner set to nacin
- Status changed from new to accepted
- Type changed from enhancement to task (blessed)
#23
follow-up:
↓ 24
@
14 years ago
For consistency with the template hierarchy, the template should be named archive-{post-type}.php
#24
in reply to:
↑ 23
@
14 years ago
Replying to scribu:
For consistency with the template hierarchy, the template should be named
archive-{post-type}.php
Here is an alternate opinion:
#25
follow-up:
↓ 27
@
14 years ago
Yeah, I've since changed my opinion. No point in introducing a new prefix.
#27
in reply to:
↑ 25
@
14 years ago
Replying to scribu:
Yeah, I've since changed my opinion. No point in introducing a new prefix.
Consistency with a confusing terminology is not a virtue.
As JohnONolan said:
#31
@
14 years ago
In [15803], I've added a few new pieces to the rewrite
flag when registering a post type. Generally that flag is a boolean, but increasingly plugins will be using it as an array:
archive
: Default false. True if you want this post type to include an archive. If this is a string, then that will be the archive slug used in lieu of the post type.feeds
: Default false. True if you want feeds as well.archive
cannot be false.
These already existed:
with_front
: Default true. Whether to prepend the front base. (When home and site urls differ.)slug
: Defaults to the post type. You can change the slug here. Note thatarchive
actually falls back to this value first.
The rewrites are kind of lame as they're straight add_rule() calls, but there's no easier way to do it without starting to move a lot of post type (and presumably taxonomy) logic into rewrite.php, which I imagine is something for a future pass or even version.
Post type archives are now is_archive = true. Previously, if done via a plugin, they were is_home = true, which was a bug as query.php is not particularly post_type-aware.
is_archive() can now check if you are on a post type archive by specifying a post type as a parameter. Note that if the plugin is for whatever reason pulling in multiple post types onto the page, then is_archive() with a post type specified should be considered unreliable. is_archive(array('post', 'page')) only checks that you are on an archive of posts or pages, not an archive of posts AND pages.
A new archive-{$post_type}.php template is now functional. Post type archives now fall back to archive.php.
#32
follow-up:
↓ 40
@
14 years ago
I don't think the 'archive' and 'feed' options should be in the 'rewrite' array simplu because they have nothing to do with rewrites.
Good to see something commited though :)
#34
follow-up:
↓ 36
@
14 years ago
Sorry, I can't hold my thoughts on this. If you have a website with a list of products, what does the term "Product Archive" mean? In business it typically means product you no longer sell. How about a site for movies; what does a "Movie Archive" mean? Frankly, I can't think of what its relevance would be on the web.
The term "Archive" only applies to content that is time-based, i.e. it would be reasonable to have an Event Archive. And even then only to things that have expired so-to-speak, and you are using the them "Archive" to apply to the normal list of posts. This is only going to confuse most people who are not already immersed in WordPress lore.
I know you don't take my input for much so I do realize you won't change on my advice, but at least I can point people to this when people ask me why theyheck WordPress chose to use such confusing terminology for something that will be so commonly used. FWIW.
-Mike
#36
in reply to:
↑ 34
;
follow-up:
↓ 37
@
14 years ago
Replying to mikeschinkel:
Sorry, I can't hold my thoughts on this. If you have a website with a list of products, what does the term "Product Archive" mean? In business it typically means product you no longer sell. How about a site for movies; what does a "Movie Archive" mean? Frankly, I can't think of what its relevance would be on the web.
I agree with you.
This is in the code, not the theme. Nowhere does the theme need to say "Product Archive." archive.php is the default catch-all for everything that is not singular, everything that is not home. Template hierarchy diagrams are very clear on this. It made sense to branch off archive templates the same way we branched off singular templates. We had single.php. Now we also have single-$post_type.php, and toggled by is_singular(). We had archive.php. Now we have archive-$post_type.php, and toggled by is_archive().
People are familiar with the template hierarchy. I have added another step to the existing template hierarchy, following what we did in 3.0 with singular templates, versus adding an entire branch.
I'm not putting my foot down on 'archive'. Personally, I don't care. I wanted this to be a non-invasive patch so I went with consistency on what we had.
Replying to scribu:
I don't think the 'archive' and 'feed' options should be in the 'rewrite' array simply because they have nothing to do with rewrites.
I don't see much of a problem with pulling those out of 'rewrite'. Only issue, is that one has a dependency of 'slug', which was already there.
#37
in reply to:
↑ 36
@
14 years ago
Replying to nacin:
Replying to mikeschinkel:
Sorry, I can't hold my thoughts on this. If you have a website with a list of products, what does the term "Product Archive" mean? In business it typically means product you no longer sell. How about a site for movies; what does a "Movie Archive" mean? Frankly, I can't think of what its relevance would be on the web.
I agree with you.
This is in the code, not the theme. Nowhere does the theme need to say "Product Archive." archive.php is the default catch-all for everything that is not singular, everything that is not home. Template hierarchy diagrams are very clear on this. It made sense to branch off archive templates the same way we branched off singular templates. We had single.php. Now we also have single-$post_type.php, and toggled by is_singular(). We had archive.php. Now we have archive-$post_type.php, and toggled by is_archive().
People are familiar with the template hierarchy. I have added another step to the existing template hierarchy, following what we did in 3.0 with singular templates, versus adding an entire branch.
I'm not putting my foot down on 'archive'. Personally, I don't care. I wanted this to be a non-invasive patch so I went with consistency on what we had.
Fair point (and good job diffusing. :)
My concern was that people will write articles about it and they will call them "Custom Post Type Archives" because the files will be called archive-%post_type%.php
and most people who write about WordPress don't ponder the fine points. Too bad we couldn't break with the past on this one, but your point about it being non-invasive is acknowledged.
Alas, inertia is a bitch. <sigh>
-Mike
#38
@
14 years ago
I think if people start calling their listing of movies "Movie Archive" simply because the file is named archive-movie.php, then there's a disconnect that I believe has nothing to do with me. :-)
#40
in reply to:
↑ 32
;
follow-ups:
↓ 43
↓ 44
@
14 years ago
Replying to scribu:
I don't think the 'archive' and 'feed' options should be in the 'rewrite' array simplu because they have nothing to do with rewrites.
If it offers a different slug for archives (older content) then it does involve rewrites. Feeds are also processed through the rewrite system.
Perhaps a couple elements could be added to the post type supports parameter: one for feed & one for archive. I like the option to have a separate/different slug for archives though and would like to see that stay.
#43
in reply to:
↑ 40
@
14 years ago
Replying to wpmuguru:
Replying to scribu:
I don't think the 'archive' and 'feed' options should be in the 'rewrite' array simplu because they have nothing to do with rewrites.
If it offers a different slug for archives (older content) then it does involve rewrites. Feeds are also processed through the rewrite system.
Feeds can also be accessed without rewrites, by adding ?feed=atom etc.
#44
in reply to:
↑ 40
@
14 years ago
Replying to wpmuguru:
I like the option to have a separate/different slug for archives [...]
Oh I'm sure I was thinking about this earlier myself? The best example I could think of is a People Post Type / Taxonomy (similar to how Matt does his photos) where the rewite is /person/
although an archive/index with that name would just sound daft. And it's where /people/
would be more appropriate!
If that's what you were on about Ron, then I agree! And if it's not quite, then I don't know if that'd be possible to do? I'm sure some code wranglers can tell me otherwise? :) I got a funny feeling you didn't mean any of the above though!
#45
follow-up:
↓ 57
@
14 years ago
- Keywords needs-patch removed
I'm thinking both arguments can stay in rewrite. Feeds work regardless with ?feed=, and archive pages work with ?post_type=, so we're only thinking about the permalinks... Does anyone else follow that logic?
Mark, that's what Ron is referring to. And yes it was part of my commit.
#46
@
14 years ago
These might belong in a new ticket, but I wanted to bring them up here before creating something new in case these were already part of the plan.
I've already started playing around with post type archives, so I've been looking for things that we would need to use within themes.
Archive title
We would need something like archive_title()
or post_type_archive_title()
. This could also be used in wp_title()
to show the title for the page.
Archive link
We would need something like get_archive_link()
or get_post_type_archive_link()
. This would allow us to link specifically to the archive page.
Conditional tag
I know we have is_archive()
and can check for specific post types with it, but we need a conditional tag to check if viewing a post type archive page. Something like is_post_type_archive()
would work better because we could check if we're viewing *any* post type archive, not just a specific one. Otherwise, you'll find yourself doing checks like this:
/* If viewing a post type archive. */ if ( is_archive() && get_query_var( 'post_type' ) )
#47
@
14 years ago
If I create archive-post_type-products.php then the H1 can simply be "Products" - it doesn't need to be dynamic because that template file will only ever serve my "Products" post type.
I think the only point of custom post type archive templates is for specific post types, there's no need for a blanket archive template because the entire point is that they're "custom" post types (eg. not related to each other).
Just my 2c
#48
follow-up:
↓ 49
@
14 years ago
If I create archive-post_type-products.php then the H1 can simply be "Products" - it doesn't need to be dynamic because that template file will only ever serve my "Products" post type.
I think the only point of custom post type archive templates is for specific post types, there's no need for a blanket archive template because the entire point is that they're "custom" post types (eg. not related to each other).
The keywords you used there were "I" and "my". Theme developers don't always make themes for themselves. They don't have the luxury of knowing what post types a user might have. They must be flexible and cater to a wide variety of uses. They must be able to create a "blanket" archive template that works across all scenarios to some degree.
I agree that custom post types are "custom" and should be handled by "custom" code. I preach that every day. But, themes should gracefully fall back to a default if no custom template, title, or whatever exists.
#49
in reply to:
↑ 48
@
14 years ago
Replying to greenshady:
They don't have the luxury of knowing what post types a user might have.
Actually, we always know. We know exactly what post types a user has because we build those post types right into the theme.
Any existing post types which they have will be replaced by the ones in the theme which is being developed. If they're going to the trouble of migrating a custom post type from one theme to another then it's fairly reasonable to assume that they might also migrate the CPT template.
Fallbacks are always good, but I don't think it's a major issue for custom post types.
#50
@
14 years ago
Actually, we always know. We know exactly what post types a user has because we build those post types right into the theme.
Any existing post types which they have will be replaced by the ones in the theme which is being developed. If they're going to the trouble of migrating a custom post type from one theme to another then it's fairly reasonable to assume that they might also migrate the CPT template.
Actually, we don't always know. Post types don't have to be developed within a theme. Plugins can also create post types. We can find out which post types are registered, of course. We don't always know beforehand (during development) which exist and should be able to create fallbacks within our themes.
For example, suppose a plugin registers the "movie" post type. The theme would normally handle the presentantion of this on the front end of the site. For the movie archive page, a theme developer cannot know to create a special template called archive-movie.php
to handle that specific archive. However, a theme developer would likely want to have a conditional within archive.php
to handle post type archives in general.
This is no different than other archive-type conditional tags such as is_category()
, is_author()
, and is_tax()
. The proposal for is_post_type_archive()
is not some weird stretch of the imagination here. It fits right in with other, similar conditional tags. The other proposed functions do as well.
Fallbacks are always good, but I don't think it's a major issue for custom post types.
I *know* it'll be a major issue. I've already done enough of these types of sites and setups with average users to know the above three things will be critical.
#51
@
14 years ago
Things that come to mind:
- Way to differentiate between pre-3.1 archive.php usage, and expanded archive.php usage -- that is, is_post_type_archive() (how would we handle post_type=post?). Debating whether we want a new query flag and make the difference more pronounced, or if it's best to be as agnostic as possible. is_post_type_archive() sounds like all we need is
! is_archive('post')
, maybe we leave it at that?
- Functions for links to the archive page, as well as feed links.
- Nav menu integration. I hate wanting to even touch this, but a simple solution might be to add a post type index checkbox to the top of View All for that post type, if that post type supports archives. Precedent here would be for the "Home" link on the Pages pane. This would however cause some additional hacking as it would be a completely new type of menu item, assuming we don't use custom links (and we wouldn't want to for ancestor/descendant reasons). Patches welcome but I don't see this happening.
- post_type_archive_title() sounds like it would just wrap post_obj->labels->name. So we just need to figure out what the best name would be for the function. And use it in wp_title().
- Body classes. Can anyone think of other templating aspects I'm missing?
#52
@
14 years ago
Way to differentiate between pre-3.1 archive.php usage, and expanded archive.php usage -- that is, is_post_type_archive() (how would we handle post_type=post?). Debating whether we want a new query flag and make the difference more pronounced, or if it's best to be as agnostic as possible. is_post_type_archive() sounds like all we need is ! is_archive('post'), maybe we leave it at that?
!is_archive( 'post' )
can probably work for the most part. However, it doesn't mean one would be viewing a post type archive page. For example, that conditional check would be true if viewing a taxonomy archive for a non-post post type.
is_archive( 'post' )
- True for any archive page displaying posts of the "post" post type.!is_archive( 'post' )
- True for any archive page displaying posts not of the "post" post type.
I like being able to use is_archive()
like this because it'll let me know what post types are in use on any archive. But, it doesn't work specifically for the post type archive/index page.
post_type_archive_title() sounds like it would just wrap post_obj->labels->name. So we just need to figure out what the best name would be for the function. And use it in wp_title().
That's the label I'd use. Similar functions are single_cat_title()
, single_term_title()
, and single_month_title()
. I'm not sure if the single_
prefix would be good here.
Body classes.
archive-post_type
would work for the body class.
#53
@
14 years ago
- Keywords has-patch added
New patch does the following:
- Adds post-type-archive and post-type-archive-{$post_type} body classes. For paginated post type archives, it additionally adds post-type-paged-$page.
rewrite['feeds']
now defaults to true, instead of false. I realized that's probably a more common use case.rewrite['archive']
needs to be true for it to work though, and it'll set itself to false if that isn't the case.
- A new query flag has been introduced, is_post_type_archive, to address shortcomings by leaving it at is_archive. With that comes WP_Query::is_post_type_archive() and a wrapper is_post_type_archive().
- I've also improved the logic that originally identified that we were dealing with a post type archive, by checking the queried post type's object to ensure we support archives. Otherwise, we fall back to is_home. This makes sense to me. However, that also means that the 'archive' parameter is no longer limited purely to rewriting (as I had said above). So maybe that one should come out of 'rewrite'. 'feeds' should stay, however.
- get_post_type_archive_link(), get_post_type_archive_feed_link(), post_type_archive_title(). The last one is then used in wp_title.
It's late and I need to get ready to leave for WCNYC, so I'm just posting the patch for now.
#55
follow-up:
↓ 56
@
14 years ago
- Cc binarybit added
- Version changed from 3.0 to 3.1
Its also very important to ensure that post type index pages (if theybare activated) have the ability of showing up in the public menu management interfece for the public site so you don't have to add them as custom links.
#56
in reply to:
↑ 55
@
14 years ago
- Version changed from 3.1 to 3.0
Replying to binarybit:
Its also very important to ensure that post type index pages (if theybare activated) have the ability of showing up in the public menu management interfece for the public site so you don't have to add them as custom links.
Patches welcome...
#57
in reply to:
↑ 45
@
14 years ago
Replying to nacin:
Mark, that's what Ron is referring to. And yes it was part of my commit.
I hate to say I only just figured that out today! :$ Works GREAT, apologies!
#61
@
14 years ago
(In [15937])
2659 2647 function is_archive( $post_types ) {
Did you mean to leave that argument there?
#72
@
14 years ago
- Resolution set to fixed
- Status changed from accepted to closed
Considering this feature complete. Please open new tickets for anything else.
We agree: this is a key omission and arguably needs to be remedied before WP 3.0's custom post types facility can be considered complete. It's logical that you'd expect, say, "books.php" (or even something like "type-books.php") automatically to receive a query containing all the entries for a corresponding custom post type "books", without having to do any custom coding. (This is the way it works for custom taxonomies.)
Currently the only way to configure a default template for a custom_post_type is to jump through hoops in the way described in the following blog post: http://www.ballyhooblog.com/custom-post-types-wordpress-30-with-template-archives/
(it involves adding custom rewrite rules AND hooking into the template_redirect to sort out which PHP template should be loaded.)