I'm running into circles trying to set up a simple rewrite rule, and thought I'd run the question by some of the rewrite experts here.

I have a custom post type, "mealplan", and I'm trying to implement a basic url rewrite where visitng site.com/mealplan/current will take the visitor to the most recent post of type "mealplan".

I've tried using several variants on this rule:

global $wp_rewrite;
  'top' ); 

... but I can't seem to get either the 'numberposts' or the 'posts_per_page' parameters to do anything in the query string like that. It just goes straight to the archive page with the default number of posts per page.

This does what I want:

global $wp_rewrite;
$current_mealplan = get_posts( array(
  'order'=>'DESC' ) );

...but at the cost of an additional query and a potential flush rules on every page load. Even if I optimize this by saving the current post ID in an option that's updated on update_post (so rules only have to be flushed when they change), this feels like unnecessary work that could be avoided if I could only get the url parameters above to work correctly.

1 Answer 1


Well, numberposts is not actually a query variable. It's just turned into posts_per_page in get_posts() before the query is run. posts_per_page is a private query var, which means you can't run it in the query string. A possible solution would be to register a custom query variable (let's say 'latest_mealplan' and add that variable to the rewrite rule (e.g. index.php?post_type=mealplan&orderby=date&order=DESC&latest_mealplan=1).

Then, hook into 'parse_request', which passes the $wp object to the callback. From there, it's just a matter of setting the parameter:

if( !empty( $wp->query_vars['latest_mealplan'] ) ){
  $wp->query_vars['posts_per_page'] = 1;
  add_filter( 'template_include', create_function( '$a', 'return locate_template(array("single-mealplan.php"));' ) );

Hope this helps!

  • Thanks, that helps a lot... I was almost there, but I was thrown by the syntax of that hook... I wasn't familiar with the context of the do_action_ref_array call. So now my url rewrite shows only one post, but its still using the archive template, not the "single-mealplan.php" template. I've tried adding $wp->is_singular = $wp->is_single = true;, but I think its too late. Is there an earlier hook I can use, before the template is set? Commented Jan 3, 2011 at 21:51
  • $wp doesn't have the value for is_single(), that'd be $wp_query->is_single. But you don't even need to touch that. Just add code to filter the template directly. I'll edit the code above to reflect that. Commented Jan 3, 2011 at 23:39
  • 1
    Actually they are both query variables, they're just not public query variables, unlike cat, tag, page, etc.. (meta_key would be an example of another private query variable).
    – t31os
    Commented Jan 4, 2011 at 15:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.