How To Create A Paginated List Of All Categories On My Site?

The question:

I want to display an archive page with pagination that lists all the categories on my site, and each link goes to that particular category archive page. So this would be like an archive page of category archives.

Each category on my site has a custom thumbnail created manually to match the category’s permalink. I already have a layout setup to display all the categories but I’m doing this with a custom page template, so there’s no pagination. This means all categories display on a single page which is a tad annoying(I have 100+ categories).

My current archive is setup with a specific custom page template name page-catlist.php but I’m willing to change this to any other type of template file.

Here’s the current code I’m using to output all categories on one page:

$args = array(
  'orderby' => 'name',
  'order' => 'ASC'
);
$cats      = get_categories( $args );
$thm_pre   = 'http://example.com/images/thumbs/';
$thm_end   = '.png';

foreach($cats as $cat) {
    $thumbnail = $thm_pre.$cat->slug.$thm_end;
    // output the loop HTML here
    // basically a list of category names & thumbs 
    // all linked to the cat URL by get_category_link()
}

I’m hoping there’s a better way to do this so that I can add natural pagination, ideally with WP-PageNavi. Any help would be greatly appreciated!

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Paging a list of terms/categories/tags are quite easy, and to achieve that, you need minimal info.

Lets look at we need

  • the amount of terms

  • the amount of terms per page

  • get_terms() (Just note, the usage of get_terms() have changed in version 4.5). You can also use get_categories() if you wish, get_categories() is just a wrapper function for get_terms()

So first we need to count the amount of terms. For this, we will use the count parameter in get_terms()

NOTE:

  • All code is untested and requires at least

    • PHP 5.4

    • WordPress 4.5

You can easily convert this to work with older versions of PHP and WordPress

$taxonomy   = 'category';
$term_count = get_terms( 
    [
        'taxonomy'  => $taxonomy,
        'fields'    => 'count'
    ]
);

Now that we know the amount of terms, we can set the amount of terms we need per page, lets say 10

$terms_per_page = 10;

From the above, we can now work out how many pages we will have. The value here will be passed to the requires pagination function, in your case, to wp_pagenavi()

$max_num_pages = ceil( $term_count/$terms_per_page );

In this case, you would pass $max_num_pages to your pagination function

The next part would be to calculate our offset. We only want to retrieve the relevant amount of terms per page to keep things optimized. We do not need all 100+ terms per page. Querying only the needed 10 is much faster. So, we need to know on which page we are, are from that, we will calculate an offset. This will be passed to get_terms(), and will tell get_terms() how many terms to skip from the initial starting point.

Once have that, we must also tell get_terms() to only return 10 terms. Let look at the code for this piece

$current_page = get_query_var( 'paged', 1 ); // Change to 'page' for static front page
$offset       = ( $terms_per_page * $current_page ) - $terms_per_page;
$terms        = get_terms(
    [
        'taxonomy' => $taxonomy,
        'order'    => 'ASC',
        'orderby'  => 'name',
        'number'   => $terms_per_page,
        'offset'   => $offset
    ]
);

You will only have 10 terms per page according to pagination. You can now just loop normally through your terms

Just a note, you would want to make sure that you actually have terms returned from your get_terms() function.

Method 2

I’m not familiar with WP-PageNavi, but I suspect it assumes to be dealing with posts, so it might easily screw up if you use it on a loop like yours. Perhaps the css might still be helpful in styling your html. Anyway, setting up your own pagination is not that difficult.

First, you need to know how many categories there are:

$cat_amounts=count($cats);

Next you need to determine how many items per page you want:

$cats_per_page=20;

This will give you the amount of pages:

$max_pages=ceil($cat_amounts/$cats_per_page);

The third piece of information you need is the page you are on. You can keep track of this by introducing a query_var Your url will then look something like this: www.example.com/yourcatpage?catpage=2

Before you start the loop, you need to know which page is called:

$page_called=get_query_var ( $catpage, 1 )

From this you can call the first element you want to display:

$first_element=($page_called-1)*$cats_per_page)

and the last one:

$last_element=$page_called*$cats_per_page-1;

The last page may contain less than $cats_per_page categories, so additionally you need:

if ($last_element > $cat_amounts) $last_element = $cat_amounts;

Now, loop through the desired elements of $cats:

for ($i=$first_element;$i=<$last_element;$i++) {
    //do your thing with $cats[$i];
}

After the loop you can use the variables to generate previous/next tags or nay other type of navigation.

Beware that I didn’t actually test this code. I may have made some mistakes when taking into account that the first element in an array has key 0.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment