WordPress 3.1 Introduces Custom Post Type Archives

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!

58 thoughts on “WordPress 3.1 Introduces Custom Post Type Archives

  1. 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?

    1. 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.

  2. 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!

    1. 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.

      1. 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.

  3. 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.

    1. 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.php template to easily theme your single entry, and WordPress 3.1 introduced the archive-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! :D

    1. Well I have never seen that before Marko, you did remember to flush your rewrite rules, and the archive-myposttype.php is 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! :)

  4. 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.

  5. 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!

    1. First up, I’m glad you found the post helpful! :) You’ll find archive-product.php only controls what you see at site.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

      1. 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?

        1. 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?

          1. 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…

          2. 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!

    2. 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?

      1. 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 use custom-post-type/custom-taxonomy as the slug value, and do remember to test it along the way! — Does that help? :)

  6. 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!

      1. Thanks for the response and now am using getarchive_where filter and am getting 404 error. I updated the permalinks too.

  7. 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 :)

    1. 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_archive argument 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!

      1. 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!)

    1. Glad you found it useful Nathan! :) And as for it being a default in the register_post_type function, 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! ;)

  8. 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

  9. 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”.

      1. 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.

        1. 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_archive is set to true or 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 … :)

          1. 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. :-)

  10. 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

  11. 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.

    1. 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.

    2. 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.php template 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_archive as false and 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!

Leave a Reply

Your email address will not be published. Required fields are marked *