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.

To achieve this, let’s first count out the things we require:

  • If the total number of pages is equal to or less than the posts per page, there should be no pagination.
  • No Previous Page link on the first page.
  • No Next Page link on the last page>
  • The current page should be highlighted

So, to achieve this, I wrote the following code, which is a mix of HTML and PHP. There’s some inline style used and rest are just bootstrap classes.:

<?php
	if($total_posts > $posts_per_page){
		$previous_page = (!empty($page_number) && ($page_number > 1)) ? $page_number-1 : '';
		$next_page = ($page_number < $total_number_of_pages) ? (empty($page_number) ? 2 : $page_number+1) : '';
		
		$one_left = '';
		$one_right = '';
		if($total_number_of_pages > 3){
			$one_left = ($page_number >= 3) ? $page_number-1 : '';
			$one_right = ($page_number >= 3) ? $page_number+1 : '3';									
		}
		
?>		
		<ul class="front_page_pagination" style="list-style-type:none;">
			<?php
				if(!empty($previous_page)){
			?>		
					<li style="list-style-type:none; float:left;"><a class="btn btn-primary" href="<?php echo site_url().'/?page_number='.$previous_page; ?>"?>">&lt;&lt; Previous Page</a></li>
			<?php
				}
				if(!empty($one_left)){
			?>
				<li style="list-style-type:none; float:left;">...</li>
			<?php
				}
			?>	
			<?php
				for($i=1;$i<=$total_number_of_pages;$i++){
					if(!empty($one_left)){
						if($i < $one_left) continue;
					}
			?>		
					<li style="list-style-type:none; float:left;"><a class="btn btn-primary" <?php if($i == $page_number || (empty($page_number) && $i == 1)) { echo 'style="background-color:#efa524"'; } ?> href="<?php echo site_url().'/?page_number='.$i; ?>"><?php echo $i; ?></a></li>
			<?php
					if(!empty($one_right)){
						if($i == $one_right) break;
					}
				}
			?>
			<?php
				if(!empty($one_right) && ($page_number != $total_number_of_pages)){
			?>
				<li style="list-style-type:none; float:left;">...</li>
			<?php
				}
			
				if(!empty($next_page)){
			?>
					<li style="list-style-type:none; float:left;"><a class="btn btn-primary" href="<?php echo site_url().'/?page_number='.$next_page; ?>">Next Page &gt;&gt;</a></li>
			<?php
				}
			?>
		</ul>
<?php
	}
?>	

The ‘for’ is the main thing that you should notice here as it is the one displaying the links. We have the $one_left set to $page_number-1 or empty as default, and $one_right set to $page_number+1 or ‘3’ as default. In the for loop we check if $i is less than $one_left we just skip the rest of the loop and if $i == $one_right we just break it all together. You can again check out the result on the homepage of this blog/website.

That’s it.

P.S: Make sure you don’t set the $_GET variable in the URI as ‘page’ e.g.: http://www.thedevlogs.com/?page=2 as ‘page’ is reserved in WordPress and it will take you to page 2 if it exists, i.e. to the URL: http://www.thedevlogs.com/page/2/

if you want the complete code in one go, here it is:

<?php 
	if(is_front_page()) {
		
		$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;
		$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);	
		
		
						

		if ( $excerpts->have_posts() ) {
?>
	<ul class="front-page-list">
		<?php
			while ( $excerpts->have_posts() ) : $excerpts->the_post();
		?>
		<li>
			<div class="thumb-and-excerpt" style="" >
				<div class="front-page-thumb"> 
					<?php	
					if ( has_post_thumbnail() ) { // check if the post has a Post Thumbnail assigned to it.
						the_post_thumbnail();
					}else {
					?>		
						<a href="<?php echo the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
							<img src="../wp-content/uploads/2015/05/phpicon.png" alt="thumb" width="100" height="100" />
						</a>
					<?php } ?>
				</div>
				<div class="front-page-excerpt">	
					<a href="<?php echo the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
						<h2 class="excerpt-title"><?php the_title(); ?></h2>
					</a>	
					<?php
						the_excerpt();
					?>
				</div>
			</div>	
		</li>
		<hr/>
		<?php
		endwhile;
		wp_reset_postdata();
		?>
	</ul>
	<?php
		}
	?>
	
	
		<?php
			if($total_posts > $posts_per_page){
				$previous_page = (!empty($page_number) && ($page_number > 1)) ? $page_number-1 : '';
				$next_page = ($page_number < $total_number_of_pages) ? (empty($page_number) ? 2 : $page_number+1) : '';
				
				$one_left = '';
				$one_right = '';
				if($total_number_of_pages > 3){
					$one_left = ($page_number >= 3) ? $page_number-1 : '';
					$one_right = ($page_number >= 3) ? $page_number+1 : '3';									
				}
				
		?>		
				<ul class="front_page_pagination" style="list-style-type:none;">
					<?php
						if(!empty($previous_page)){
					?>		
							<li style="list-style-type:none; float:left;"><a class="btn btn-primary" href="<?php echo site_url().'/?page_number='.$previous_page; ?>">&lt;&lt; Previous Page</a></li>
					<?php
						}
						if(!empty($one_left)){
					?>
						<li style="list-style-type:none; float:left;">...</li>
					<?php
						}
					?>	
					<?php
						for($i=1;$i<=$total_number_of_pages;$i++){
							if(!empty($one_left)){
								if($i < $one_left) continue;
							}
					?>		
							<li style="list-style-type:none; float:left;"><a class="btn btn-primary" <?php if($i == $page_number || (empty($page_number) && $i == 1)) { echo 'style="background-color:#efa524"'; } ?> href="<?php echo site_url().'/?page_number='.$i; ?>"><?php echo $i; ?></a></li>
					<?php
							if(!empty($one_right)){
								if($i == $one_right) break;
							}
						}
					?>
					<?php
						if(!empty($one_right) && ($page_number != $total_number_of_pages)){
					?>
						<li style="list-style-type:none; float:left;">...</li>
					<?php
						}
					
						if(!empty($next_page)){
					?>
							<li style="list-style-type:none; float:left;"><a class="btn btn-primary" href="<?php echo site_url().'/?page_number='.$next_page; ?>">Next Page &gt;&gt;</a></li>
					<?php
						}
					?>
				</ul>
		<?php
			}
		?>	
<?php
}
	
?>

Happy Coding 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *