While development on WordPress 3.1 is still ongoing and we’ll probably not see the final release until nearer the end of the year, I thought I’d let you know about a cool new addition to Custom Post Types that Andrew Nacin (Core Developer) worked on!
Little Background Info
Around 5 months ago #13818 was opened requesting an Index/Archive option for Custom Post Types because the way WordPress works meant that /post-type/ would just 404 on you although /post-type/wordpress-rocks/ worked just fine.
Similar could be said about Custom Taxonomies and how they function which I brought up back in February on the WP-Hackers Mailing List – I don’t think I was popular in the community that month for sure? While it’d be a nice addition I know many would like (and shut me up) I have been informed more than once it’ll not happen!
Now For Some Code
If you’re new to Custom Post Types and the register_post_type(); function then make sure to check out an in-depth article Justin Tadlock wrote on the subject, I recommend you read it anyway! :)
In our functions.php file lets setup a basic Projects Post Type with the Archive active.
add_action( 'init', 'mcw_projects_post_type' );
function mcw_projects_post_type() {
register_post_type( 'projects', array(
'labels' => array(
'name' => __('Projects'),
'singular_name' => __('Project')
),
'public' => true,
'show_ui' => true,
'rewrite' => array(
'slug' => 'project',
'with_front' => false
),
'has_archive' => true
) );
}
We’re looking at the has_archive argument which has been set to true which will turn on the Archive for this particular Custom Post Type, normally it would default to false though! — But we can take that a step further because when it’s set to true it’ll fallback to the value in the slug argument. So here that would make it site.com/project/ which just wouldn’t look quite right!
'has_archive' => 'projects'
All we did was substitute true with projects which therefore shows site.com/projects/ as being home instead. Now we know we can do that, we can do all sorts of things (get creative), we don’t need to keep it in line with our Projects Post Type.
'has_archive' => 'work'
Thinking outside-the-box gives you site.com/work/ which is different, the option is yours!
What Else Might I Need To Know
A new archive-{$post_type}.php template was introduced although it will fallback to archive.php if it can’t find the appropriate template for the job. So for our Projects Post Type, as projects happens to be the value we used for the Custom Post Type, we’d call our template archive-projects.php — Similar to if we used the portfolio value for a Portfolio Post Type we’d end up calling our template archive-portfolio.php and so on.
If you get a 404 error when trying to view the Custom Post Type Archive then simply visit Settings > Permalink which will flush your rewrite rules for you, it’s as simple as that, and there we have it!
I have been waiting for how this would be implemented in ver 3.1… thanks for this. Are there plans for how someone might display a custom post type archive in the nav menu?
To my knowledge nothing has been done about that yet Tom, although patches are welcome if anyone would like to offer a hand? As it stands right now though adding a Custom Link would work, but I see where you’re coming from as do many others.
Great post Mark. This should be a really nice addition for anyone looking to really get their value out of custom post types on a site!
Indeed, thanks, and glad you liked it Michael!
I wonder if this will fix the issue I’ve been having. I use page templates for all my CPTs. Each querying their CPT. But each CPT page template has no way of knowing its relation to the home page I guess, so each thinks its the home page. This messes up a few things; breadcrumbs, all the CPT templates come up as home, but when you click home, you get to the real home; SEO plugins, all CPT templates get the SEO info of the home page, rather than their own; and Nav Menu, none of the CPT templates come up as current-menu-item, instead the Home page always highlights when on any of the CPTs.
So hopefully this new feature clears that up!
Well, I just put the RC1 on my dev install, and it fixes the issue with current-menu-item. So that’s the major issue resolved for me. I’m goping to wait and see if the plugin/breadcrumb/seo stuff resolves for the full release….when I upgrade my main install. I’m too lazy to install all the plugins on my dev install atm. Thanks for the write-up, it helped me get things going and understanding the archive function for my CPTs.
Glad to hear you’ve got things working! :) With the RC1 release it means 3.1 is pretty much ready for the final release, but they just want to put it out there for any last-minute bugs/problems anyone happens to find? Hope to write more about WordPress in general as I do exciting stuff with it, so watch this space as they say.
Excellent post, thanks. Much appreciated.
Glad you found it useful! :)
It may be worth mentioning that you might have to flush your rewrite rules for this to take affect. I usually just go to the permalink settings and click on update without changing anything.
Thanks for that Daniel, you can see the little addition I made at the end of the article, these things slip your mind when you’re writing! :)
Is there a way i can redirect custom post types to a subfolder in my theme? just like feature 3 from http://somadesign.ca/projects/smarter-custom-post-types/
So if i have a custom post type named reviews, all i have to do is create a folder reviews with single.php , index.php and archive.php?
Any tips, thoughts?
Not that I’m aware of, without writing some extra code anyway? But in my opinion anyway, why would you; WordPress 3.0 introduced a
single-posttype.phptemplate to easily theme your single entry, and WordPress 3.1 introduced thearchive-posttype.php(as mentioned above) to easily theme your Custom Post Type Archive too! — Back before 3.1 the Smarter Custom Post Types was very handy, and useful (credit to the author), I feel it’s now built-in to the WordPress Core! :DThanks for the info! What if template file is not working (recognizing) ?? I have template archive-myposttype.php but I get redirected to home page…
Well I have never seen that before Marko, you did remember to flush your rewrite rules, and the
archive-myposttype.phpis properly named? I’ll send you an email at the one you used here, and we’ll go from there. Glad you found the information handy though! :)Thanks for the post. I’m wondering, is there any interface available for including custom post type archives into nav menus? I can’t see one. Of course I can add a Custom Link, but I would have assumed that as you can add actual custom posts to nav menus, you’d also be able to add the archive pages.
In short Steve, not at the moment anyway! [Edit: Although you might be interested in following #16075 on WordPress Trac and try out any patches attached, then report back with your results!] :)
Hi Mark
Thanks for this great post. But there’s somewhere that archive-posttype is failing (or I’m doing it wrong). Say I have a post type called product. And I have a custom taxonomy, heirarchical, containing, say, Fall, Spring, Summer. I’ve set up the rewrite rules so it goes to mysite/product/fall and mysite/product/sprint, etc. however, the archive template isn’t called on these custom taxonomy pages. So, mysite/product (the “archive” for the post type) correctly calls archive-product.php. But mysite/product/fall/ calls the normal archive.php file. This is unfortunate behavior; it seems that the template heirarchy is not respecting the post type and respecting instead the archive slug… Do you know if I’m doing something wrong or how I can fix this other than just checking within archive.php with many if/else statements (unfortunate and buggy)
Thanks!
First up, I’m glad you found the post helpful! :) You’ll find
archive-product.phponly controls what you see atsite.com/products/if we go with your example above, but a point to remember, Custom Post Types and Custom Taxonomies are different and use different templates!For anything (Custom) Taxonomy related, you might like to read the segment about them on the Codex, which I hope will help? :D
mark,
thanks for the reply! you’re absolutely right, but i think its a failure in the WP heirarchy. in my opionion, the heirarchy for custom post types should priviledge the TYPE over the TAXONOMY. so, if i visit a taxonomy, it should check the posttype first, and then do the tax…
visit taxonomy:
1. taxonomy-posttype.php
2. archive-posttype.php
3. taxonomy-taxonomyname.php
4. taxonomy.php
5. archive.php
6. index.php
etc… what do you think?
While I think the Template Hierarchy could be looked at in a future version of WordPress, and quite possibly updated (or enhanced might sound better), I don’t agree it should make checks like you suggest (each to their own!)
If you take a look around ThemeHybrid.com and see how Justin Tadlock has done certain things to modify the way the Hierarchy works with Hybrid Core? — It might be a good start if you wanted to roll your own method too?
hey matt, no problem, i will. but through a more philosophical argument ( :-) ) don’t you think that a post type should always trump taxonomy or category? the point being that it is something way different from other things.. so the way that “something” is taxonomied is actually not as important as that the thing is different…
You mean Mark right, not Matt? ;) In answer to that question, no I don’t think that should be the case, they’re completely different from one another; therefore it makes logical sense (in my opinion) to use different templates!
Your rewrite rules sound like what I’m after…
I’d be grateful if you could point me in the right direction for mysite/custom_post_type/custom_taxonomy …?
Is there a ‘quick fix’ or not as such?
I have seen a couple of people playing around with different URL structures before, doing something very similar. Something like
mysite.com/custom-post-type/custom-taxonomy/taxonomy-term/could well be achieved. When you register your Custom Taxonomy, just usecustom-post-type/custom-taxonomyas theslugvalue, and do remember to test it along the way! — Does that help? :)Hi Mark,
Thanks for the post, seems really promising but am not getting it work for me. I have a custom post(abc) with it’s own archive template (archive-abc.php) and default post for blog and am using wp_get_archives() function to list archives but the archive link directs me to the default post archives.
It would be a great help if you could guide me through this.
Thanks!
I think this could be the same problem Marko was experiencing! To get
wp_get_archives();working with Custom Post Types, you’ll need to take advantage of thegetarchives_wherefilter. There are a couple of articles on the subject that should at least help get you started, do let me know how it goes. Glad you enjoyed the article though! :)Thanks for the response and now am using getarchive_where filter and am getting 404 error. I updated the permalinks too.
Thanks for a great post Mark. I’d been struggling with getting the archive to work (didn’t want to resort to a plug in) but your clear instructions helped a great deal.
Glad I could help you out James! :)
Hi Mark, thanks for the article!
I’m having some troubles with custom post type archives.
Type is called ‘photo’ and ‘has_archive’ => ‘photography’. I have archive-photo.php, have flushed the rules, am using WP 3.1.1… and still, when I visit localsite/photography/ it returns 404.
Also, how can I have taxonomy arhives? If tax is called ‘portfolio’, I want it to be accessible via localsite/portfolio/ but its not, 404 returned again. And I don’t really fancy creating a separate page template for that :)
Thanks again :)
First up Darko, I’m really glad you found the information helpful. To answer your first question, in WordPress 3.1 if you have an empty Custom Post Type (which basically means it’s got no posts) then the archive will 404 on you. There was a ticket submitted, and patched, to change that behaviour for WordPress 3.2 — So just add something in there, even if it’s got dummy content! :)
For your second question, it’s currently not possible to use the
has_archiveargument like you would in a CPT, which I’d love to see myself! The only way you could achieve a similar result would be going down the route you mentioned above, and creating a Custom Page Template for each archive page you were after; it’s not ideal I know!Thanks! :)
I guess I’ll try to automate the process of creating a Custom Page Template for taxonomy archives. Maybe something around ‘template_redirect’? Or simply manually create the page when theme gets activated…
By the way, I have obviously messed something up with my (own) theme, since it shows 404 even when CPT isn’t empty. And now I’ve tried it as a plugin on Twenty Ten, its working! Will let you know what the problem was. (suspicious about some custom $wp_rewrite rules!)
Thank you! I spent forever trying to figure this out, seems like it should be default for the register_post_type function to create this page.
Glad you found it useful Nathan! :) And as for it being a default in the
register_post_typefunction, it’s all about how you implement your Custom Post Type(s), not everyone is going to keep them similar to normal posts! — Just be thankful that functionality is available for use! ;)Hi there,
I’ve been trying to solve this issue for so long now…I have everything set as I think it all should be working. I have a custom archive page for my cpt, which lists the posts of the CPT, and custom template to display the cpt…all of this works, but I just cannot get the month archive to work.
If my CPT archive page can be found at http://localhost/egi/testcpt/ then what should the URL be to show posts for January 2012, because http://localhost/egi/testcpt/2012/01 does not work, just returns 404….. PLEASE can somebody help me on this…driving mi nutz
I know Umesh asked a similar question further up in the comments. I pointed out a few articles on the subject, see if they’re of any use to you? If you’re still stuck, it might be a good idea to search on the WordPress Stack Exchange and see if that question has been asked before? :)
Thanks for great tutorial Mark, but do you have any ideas how I could link to the archive page with custom post types when Default structure of permalinks is enabled? I’ve tried everything I could, and nothing works: “mysite.com/?projects”.
Glad you found it useful Pavel, thanks! :)
Mind totally went blank, but after checking with Andrew Nacin, he confirms that you can view the archive with the ugly (
?p=123) permalinks. Simply visit?post_type=$post_typeto achieve the result you’re after. If you’ve sethas_archivetofalsethough, it’ll not work! Hope that helps?Thank you for this, it was very handy. I’ve got my CPT archive page working if I use ?post_type=$post_type but I haven’t been able to figure out the permalink settings to get my archive page to display with just /$post_type/.
Is there a specific permalink structure required to get this to work? I’ve tried all of the “common” ones on the permalink settings page.
You need to have what’s classed as pretty permalinks “turned on” so to speak. (Anything other than the default setting.)
After that, make sure
has_archiveis set totrueor the custom slug you’re after, then visit/projects/as per the example shown in the article.If that doesn’t solve things, then there’s a conflict somewhere that’s causing some kind of problem? I’d be happy to take a quick look for you … :)
Hmm, I did both of those things and it still didn’t work for me. Maybe something’s up in my htaccess file. Thanks for the offer to take a look but I’m working inside a vpn. I’ve been working on other things but if it becomes important, I’ll figure this out eventually. :-)
It may well be a
.htaccessfile error? Does it look something like the example shown here (the link), or different?Well the offer is still there, just give me a shout.
Any ideas on getting this to work with dates and pagination?
For example:
myurl.com/2012/10/my-custom-post-type/
myurl.com/2012/10/my-custom-post-type/page/2/
Thanks,
Rich
Umesh asked a very similar question over a year ago now, and to my knowledge, nothing has changed in core to change how you would get the same result. You need to use the
getarchives_wherefilter as explained in one of my earlier comments!I’ve personally never tried it out myself before, so the few artitles linked should help with that. Let me know how you get on!
Hi Mark and thanks for this article, best one I could find on the topic.
I was able to set up an archive page for my custom post type. By default it shows a list of all posts created under the post type., however I need to show only one page (which is the “homepage” for this section).
I modified the archive-my-post-type.php template to only show that one post. However that one post exists on it’s own under http://www.mysite.com/customposttype/my-post-that-is-also-homepage/
So now I solved the problem of having this on the homepage, but have the same content in two pages (bad SEO). I 301 redirected the post to the custom post type homepage. Hope this all makes sense!
I’m wandering if this sounds like a good solution and / or if there is a better way to do this.
In case I wasn’t clear enough :) …
my goal is to have an “index” or “homepage” for custom post types, just what the article addresses, but this “index” page is not an archive (blogroll) page, but a single page created under this custom type. The issue with my solution is duplicate content (post is displayed in “index” but also it exists on its own). My current solution is 301 redirect the actual post.
Perfectly clear Taulant, was following along just nicely. First up, thanks for the very kind comments regarding the article, and I’m glad you found it of some use.
I remember reading something a while ago which asked for an editor, and an option, be included so you could “edit” the custom post type archive, or index as it’s also been called. All because people, like yourself, want to break free from the traditional blog look. (It must have been on Trac, but I can’t find the ticket number!)
Have you got a link handy of the site in question? :)
If we take the
archive-projects.phptemplate from the example shown in the article, you could effectively remove the code which calls the posts, and replace it with a copy of this homepage. Not ideal though, I’ll say that.Another option might be to set
has_archiveasfalseand create a page with the same slug, which would then allow you to easily edit things through the WordPress editor.I’m sure there are other options we could explore, but until I see what we’re playing with, your best bet is probably going with the option above.
Let me know how things go, and give me a shout if you need a hand!
Excellent info,This should boost custom post types on a site!
Thanks ,
Cam