1

I want to number "product" post types according to their position in their archive. Currently, I have tried to do this by creating a counter variable $count and incrementing it in the loop in my archive template, archive-product.php:

<?php 
  $count=0;

  while ( have_posts() ) : the_post();

    echo("<br />Count=" . $count . " eind count <br />");
    $count++;
    get_template_part( 'content', 'product' );

  endwhile; // end of the loop.
?>

However as a result of pagination, this solution starts counting from 0 again for every page of products - so when displaying 10 items per page, every page displays the numbers 0 through 9.

How can I consistently number my products such that each page picks up where the last one left off (i.e. page one displays the numbers 1-10, page two displays 11-20, etc.)?

1
  • Welcome to the WordPress community @matthijs100! Unfortunately, questions regarding 3rd-party products are off-topic as described by our help center. However, in a more general form your question applies to the WordPress community at large, so I have filed an edit towards that end
    – bosco
    Commented Sep 15, 2015 at 3:14

1 Answer 1

1

The concept of dividing up a set of posts into a number of "pages" is called Pagination, and is controlled by a number of pagination parameters in a WordPress posts query. The three most relevant (and most commonly used) are:

  • posts_per_page: the number of posts displayed on each page
  • paged: which page of posts is currently being displayed (note that on a static front page and single posts broken up into "pages", the page number is represented by the page parameter instead)
  • offset: the number of posts to "skip over", or the number of posts on previous pages. This overrides the paged parameter (and so the two are used in different circumstances) - but can usually be calculated from the other two parameters

WordPress provides the means to get the values of these query parameters by way of get_query_var(), so you can retrieve them as such:

// Retrieve posts_per_page query variable defaulting to -1 to indicate all posts on one page
$posts_per_page = get_query_var( 'posts_per_page', -1 );

// Retrieve the page number from 'paged', defaulting to false if not found
$page_number = get_query_var( 'paged', false );

// If the page number couldn't be retrieved from 'paged', try 'page', and assume page number 1 if it can't be found there, either.
if( !$page_number )
  $page_number = get_query_var( 'page', 1 );

// Retrieve the number of posts on previous pages, defaulting to 0
$offset = get_query_var( 'offset', 0 );

Knowing the values of those query arguments allows you to get the current post's index within paginated query results with either of the following expressions:

{number of previous posts} + {current post index within this page}
// OR, since {number of previous posts} = {number of posts per page} * {page number}:
{number of posts per page} * {page number} + {current post index within this page}

The only piece that's missing is {current post index within this page}, which in your question you are acquiring by creating and incrementing the $count variable - but here too WordPress provides another means to access this data within The Loop: the $current_post property of the WP_Query object, which can be accessed for the main query through the $query global variable:

// Within The Loop, holds the index of the current post item within the query results array (starting from 0 for the first post)
$post_index = $query->current_post;

So, putting it all together into your Loop, the following should correctly list each post's index within paginated query results, regardless of how the query was set up (though it does not presently take into account the posts_per_archive_page query parameter):

<?php
  // Retrieve the number of posts from previous pages
  $index_offset = get_query_var( 'offset', false );

  // If the number of posts on previous pages could not be retrieved, calculate it
  if( ! $index_offset ) {
    // Retrieve posts_per_page query variable defaulting to -1 to indicate all posts on one page
    $posts_per_page = get_query_var( 'posts_per_page', -1 );

    /* Retrieve the page number, or assume page number 1 if it's not set anywhere (done here
       in shorthand using the "tertiary operator") */
    $page_number = get_query_var( 'paged', false )
      ? get_query_var( 'paged' )
      : get_query_var( 'page', 1 );

    // If pagination is enabled and we're not on the first page, calculate the offset
    if( $posts_per_page > 0 && $page_number > 1 )
      $index_offset = $posts_per_page * $page_number;
    else
      $index_offset = 0; // Otherwise, indicate that there are no posts before this page
  }

  // The Loop
  while( have_posts() ) {
    the_post();

    /* Set the post index to it's position in the query results, PLUS the number of
       posts on previous pages, and add 1 to start counting from 1 instead of 0 */
    $post_index = $query->current_post + $index_offset + 1;

    // Now display $post_index before the post's title:
  ?>

    <div id="post_<?php the_ID(); ?>" <?php post_class(); ?>>
      <h3 class="post-title"><?php echo( $post_index ); ?>. <?php the_title(); ?></h3>
      <?php the_content(); ?>
    </div>

  <?php
  } // End The Loop
?>

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.