Updates 6 Feb 14 to make more specific as requested in comments.
I have a post type, we’ll call it “Projects”, with the slug “projects” for which I’d like to offer two views:
- list view (default)
- map view
I’d like those views to be at the following permalinks:
- example.org/projects/ (default post type archive page,
archive-projects.php
) - example.org/projects/map/
How do I do handle instructing WordPress to use a specific template when accessing that one specific URL that would otherwise imply a specific Projects post? It would be nice if that redirect managed to keep the default post type archive query, but I can write a secondary loop in the template if necessary. I had initially thought endpoints were the answer, but I’m pretty sure that’s not true.
Original Post
I have a post typeâ”Projects”âfor which I’d like two views of its post type archive. The first is a pretty-straight forward list of Projects sorted by category and the second is a mapped view of the projects. Making templates for those two views is not a problem.
How can I make these two different views of the Post Type Archive, each with a unique URL?
Ideally I’d like the first template to be the default at /projects/
and the second view at /projects/map/
.
It seemed like a custom endpoint was the way to go, but this comment on an old question with a title that perfectly describes what I’m looking for suggests that there is no way to have an end point for only a custom post type archive.
Should I use a custom rewrite, then, or should I even consider going with a more jQuery driven solution?
Updated approach
The first thought/suggestion I made actually – like you said – doesn’t work as I understood it. At least I tried it and couldn’t figure it out. That said, what you want is still achievable, but not by using a endpoint or at least not by making use of
add_rewrite_endpoint()
.However I figured it should be possible via a “ordinary” rewrite setup. Below code shows how to setup a post type, a query variable and a rewrite rule, to make a custom view for the post type archive possible. Last but not least we need to make sure to load the correct template. This it is possible to kind of emulate an endpoint. The exemplary code should get you in the right direction, so you can adapt it to your needs.
Code:
Answer to comment
To be honest I reused some code I’ve written some time ago, I only adapted it a bit to make it fit to your needs. There I used the above approach, with the
$wp
global. But that of course is no explanation for the why, so I try to address that too.If I’m not totally absolutely mistaken
add_query_var()
is only available as function/method of theWP
class. So the above way is just the way to do it.Regarding
get_query_var()
, this one you could use instead, but it globalizes$wp_query
and uses theget()
function/method of theWP_Query
class. So in a way the difference isn’t or shouldn’t be a big one.Besides that, one more thought, the
WP_Query
object is likely to be bigger than theWP
object, if not always. So doing it via global$wp
might actually be a good thing.But actually I didn’t thought and tested this trough, I’ve used it like this and it is working in my setup, so I was satisfied when I did that code. So there might be a drawback in another setup/use case. Or doing it another way might be more valuable/beneficial in other cases. But like I said above, this is to get you started, you have to adapt it to your needs yourself.
Update after comment
As @mrwweb pointed out and above linked article explains it, the
template_redirect
filter isn’t optimal for choosing a different template. Or as @MarkJaquith simply concludes:He convinced me, so I changed the way the »aview« template loads to the
template_include
filter in above code.First thought/approach
Disclaimer:
I’m keeping this, because of it’s informational value, but this won’t work for the custom post type archive. However using
ep_mask
comes in handy for creating endpoints for the single custom post type posts.From what I understand, endpoints can be done in such cases. I recently read into that, but never actually had to approach doing it. So this is to the best of my knowledge, maybe someone with a lot more of it will come by and clear things up.You’re right with what you said:
So making use of the
ep_mask
parameter like described below can be used for the posts of a custom post type, but not for the archive. Beside that, playing with this made me realize how handy a customep_mask
can be for the single custom post type endpoint creation.Basically what I read pinnacled into making use of the
ep_mask
argument you’ve available when usingregister_post_type()
and
register_taxonomy()
rewrite
argument.Take a look at the related trac ticket 19275. You can find additional possibly helpful information at the
register_post_type()
codex page at thepermalink_epmask
description, especially trac ticket 12605.As for an overview about endpoints:
Here is an answer on:
for categories there already is
EP_CATEGORIES
of course, but it shows that it really should be possible, if you make use of theep_mask
argument.Update 03/12/17
The plugin mentioned below is abandoned, what I currently maintain is another package, Cortex
Consider my answer just as an alternative.
I developed a plugin, Clever Rules, that allows to specify a route, a query and (among other things) a specific template.
What you need using Clever Rules is register a rule, but please note that with current version you can register rules only in plugins, not in themes.
Download Clever Rules, activate it. Now you need a plugin to register your rules: you can create a new plugin, or insert the following code in a plugin you are developing…
This 3 lines of code is the only thing you need. If you created a new plugin for that, activate it, of course.
No one of the default urls will be affected.
‘your-specific-template.php’ can be a template file in parent or even child theme.
Of course you can customize the query just like you want and use other plugin features.
And if you like the system, you can use the same plugi to register all the rules you need.
Notes
I am developing a new version of that plugin, that will be a bit more performant (when there are a lot of rules, only one is not a problem), allow rules registration in themes, has a little different API and some additional features. It will be public released soon, however, the current version works too.