Can ‘numberposts’ be passed in the URL query string?

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

Read More

I’ve tried using several variants on this rule:

global $wp_rewrite;
$wp_rewrite->add_rule('mealplan/current', 
  'index.php?post_type=mealplan&numberposts=1&orderby=date&order=DESC', 
  '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(
  'post_type'=>'mealplan',
  'numberposts'=>1,
  'orderby'=>'date',
  'order'=>'DESC' ) );
$wp_rewrite->add_rule('mealplan/current', 
  'index.php?post_type=mealplan&post_id='.$current_mealplan[0]->ID, 
  'top');

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

Related posts

Leave a Reply

1 comment

  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!