WordPress is by far the most popular CMS in the world especially for blogs related website. One reason for that is cause it has almost everything a developer needs, right out of the box. For everything it doesn’t have, somewhere out there is a plugin just for that. Customizing front-ends within minutes by applying themes is just one of the many features that makes it great. But a wise man once told me that you can’t have all the happiness in the world at once, and so it is with WordPress. You see, on this very blog website, I have applied a very simple theme and I like the simplicity it has. Just a few menu links and nothing too shiny and fancy. But this is not what you get in the default theme. I wanted to have a simple theme but also wanted to have a list of blog posts that I post right on the home page, which was not a part of this or any other similar theme for that matter. So I decided to have a customized front page of my own in this theme. What I wanted was a page displaying all my blog posts in a list that is paginated. The default template for the pages is page.php, and since I didn’t want to create a separate front-page.php, I decided to work on the page.php file itself and work in the conditional statement

if(is_front_page()) {}

to only display the blog posts list on the front page only. A list which can have more than 5 elements should also have pagination to it, this should be treated more as a convention rather than a preference. So, if you are looking for displaying posts with excerpts or even want to check out pagination then this post i.e. “WordPress Custom Pagination and Blog Posts List” might keep you interested.

So, the first thing you want to achieve is to display the list of all the blog posts. My requirement in addition to that was also to display the posts excerpts (a short extract from the content text) along with the title and the featured image, with respect to every post. If you want to check the desired result, just check out the homepage of this site at: here.

Now, the first thing that might come to your mind might be that all this requires is some sort of DB query to get the desired results, and you would be right. If you’ll look at the database of a WordPress site you might notice the table wp_posts, this is the table that’s responsible for storing your posts and pages content and managing their status as ‘draft’ and ‘published’. So, a query to fetch the results from the DB with all the posts might look like:

SELECT * FROM `wp_posts` where post_status = 'publish' and post_type = 'post';

. Fortunately, WordPress offers us an easier way to deal with querying the DB, i.e. using the WP_Query class. So to query our DB and get the blog posts, we’ll right something like:

$excerpts = new WP_Query( array(
				'post_type' => 'post',
				'post_status' => 'publish'
				));

The $excerpts is the variable to hold the result given by the WP_Query object. The WP_Query class takes the arguments in an array format. To know better about the WP_Query class and it’s uses, it’s better if you’ll visit the link: https://codex.wordpress.org/Class_Reference/WP_Query, rather than me explaining it to you. Next thing is just to loop around the $excerpts object using the WordPress inbuilt functions have_posts() and the_post() functions. It should look like this:

if ( $excerpts->have_posts() ) {
  while ( $excerpts->have_posts() ) :
  $excerpts->the_post();
  if ( has_post_thumbnail() ) { // check if the post has a Post Thumbnail assigned to it.
	the_post_thumbnail();
  }else {
	//The path to the default thumbnail link
  }

//The individual post link, it's title and it's excerpt can be achieved using the functions: 
//the_permalink(), the_title() and the_excerpt() functions, respectively, within the 'while ( $excerpts->have_posts() ) :' loop.

This is all good and it basically gives us the list we want. But we also need pagination, which is probably the thing you’d be interested in this post. So, to achieve pagination, ijn any other environment, we most probably use the ‘limit’ and ‘offset’ statements of MySQL, like:

SELECT * FROM `wp_posts` WHERE post_status = 'publish' and post_type = 'post' LIMIT 0, 5;

. In the aforementioned SQL query LIMIT 0,5 means that ‘0’ is the offset i.e. the result should start from the 1st row and 5 is the limit, i.e. it should display only 5 rows. As we are using the WP_Query class for our query we have to pass arguments to it matching these limit constraints. So, our $excerpts object would now look like:

$excerpts = new WP_Query( array(
				// 'post_type' => 'post',
				'post_status' => 'publish',
				'posts_per_page' => $posts_per_page,
				'offset' => !empty($page_number) ? $posts_per_page*($page_number-1) : $page_number
				));

Noticed that I have commented out the ‘post_type’ key, that’s because the default value for the post_type key is ‘post’, so you don’t have to mention it. The ‘limit’ of our query is set by the ‘posts_per_page’ ket and the ‘offset’ is set by the ‘offset’ key itself. The value of both is set by a variable in our example as we need to access that in multiple places and also need it to be dynamic based on the user choice.

To understand the logic behind the value of ‘offset’ key, consider this:
(For the sake of understanding let’s assume that all the posts have an id from 1 onward, 1 being the most latest post, so all posts have id like 1,2,3…..n. By default, WordPress always return with the latest post on top and then descending)
Let’s say we have the value of ‘posts_per_page’ to be 3 and the user is at page number 2. So, in this case the user should see the posts 4,5 and 6. This means that the value of the ‘offset’ key should be 3, which is equal to the ‘posts_per_page’. Now, the user moves to the page number 3, in this case the value of the ‘offset’ key should be 6 and the the user should see the posts 7,8 and 9. And so on for the next pages as well. Judging from this, we can derive a formula to set the offset dynamically, which is: $posts_per_page*($page_number-1). Since for page number 3, we can test our formula on it as: 3(3-1), therefore the ‘offset’ key value is 6. For page number 4, the ‘offset’ value should be 9, applying our formula for page number 4, 3(4-1) = 9, which is correct. This is all well, but what if there is no page number or if the user is at page number 1, in this case our formula will give an unexpected result, but we know that on page number 1 or when there is no page number, the offset should be equal to 0. For page number 1 our formula gives 3(1-1) = 0, which is correct and when there’s no page number, it will be considered as empty and will go to the ‘else’ condition of our code i.e. after the colon ‘:’ sign.

To set everything ijn motion we need to have certain variables set above the $excerpts object. The $page_number variable will actually be the one set in the $_GET global variable set in the URI itself. So the whole code should look like this:

$count_posts = wp_count_posts();
$total_posts = $count_posts->publish;


$page_number = !empty($_GET['page_number']) ? $_GET['page_number'] : 0;
$page_number = !ctype_digit($page_number) ? (int)0 : (int)$page_number; //in case someone manually enters the page_number value in the URI and it's not an int.
$posts_per_page = 5;
					
$excerpts = new WP_Query( array(
				// 'post_type' => 'post',
				'post_status' => 'publish',
				'posts_per_page' => $posts_per_page,
				'offset' => !empty($page_number) ? $posts_per_page*($page_number-1) : $page_number
				));

$total_number_of_pages = $total_posts/$posts_per_page;	
$total_number_of_pages = ceil($total_number_of_pages);	

Now all that’s left is to display the pagination links of the pages 1 to n (n being the last page). This seems easy, right, but I have something interesting to add here. I figured that Let’s say if someone have 100 of post and the post per page is set to 5, in that case the number of links will be 20, and if someone have 500 post it could reach as high as 100 links and so on… which is definitely not good. I have seen some sites display page links like that. So, I decided that I’ll just display 3 page links at most, one to the left and other to the right, with obvious previous page and next page links. When I’ll have much more posts I’ll display 5 page links at most, but for now I think 3 should be sufficient.

More »