How I solved pagination in PHP.
Tags: php, oop, webdev, showdev
Published: 2019-11-29 14:40:46

###**Hi everyone,**

This is my first post here, but I'll try my best to format it properly and explain everything correctly, although I'm really bad at professional speech, I can't really talk like a real programmer sadly, so I'll mostly just use regular words and expressions.

So, I think everyone is familiar with the term `pagination`.
For quite a while I spent a lot of time searching for the simplest pagination solutions on the internet, since  unfortunatelly I didn't have the knowledge to do it by myself.

But there was a huge problem: every solution I've seen was either outdated, or extremely overcomplicated, yet were called *"simple"*, like people were just trying to show off their skills, instead of actually trying to help others. Or another problem was that most of them **were not dynamic at all.**

One night, my brain just wouldn't stop searching for possible solutions, and suddenly I came up with one, which I coded and tested on paper that night. I believe this code is not complicated at all, it's easy to understand, yet works perfectly. In this example we are separating comments into pages. The following examples use a little bit of Bootstrap and Jquery.

First, here is the final result:

**Desktop view**
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/2xbu46d8lqewm7k6fdeu.jpg)

**Mobile view**

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/6lzabysgu2gjvn291u2e.jpg)

Now let's go through the code, step by step.

1.**Counting the comments**

Here we just have this function called `countAllComment()`with simple `prepared statement`, which returns with the number of comments, in `classes/comments.php`. Nothing new so far.

```php
function countAllComments(){
	$st=$this->conn->prepare("SELECT COUNT(*) FROM comments");
	$st->execute();
	return $st->fetchColumn();
}

```

2.**Let's define some variables we will need, in `index.php`**


```php
require("classes/comments.php");
$comments=new Comments();
require("classes/pagination.php");
$pb=new PageButtons();

$total = $comments->countAllComments();//overall number of comments
$per_page = 15; //comments to display/page
$limit_start = ($_GET['page']*$per_page)-$per_page;
$all_pages = ceil($total/$per_page);//number of all pages
$page_diff = $all_pages-$_GET['page'];//difference between current page and number of all pages
$base_link = "/comments/";//or any other link
$next_link = $base_link.($_GET['page']+1);//leads to next page
$prev_link = $base_link.($_GET['page']-1);//leads to previous page
$next_next_link = $base_link.($_GET['page']+2);//jumps 2 pages forward
$prev_prev_link = $base_link.($_GET['page']-2);//jumps 2 pages back
$last_link = $base_link.$all_pages;//leads to the last page
$first_link = $base_link."1";//leads to the first page
```

3.**Creating the function which draws the buttons, called `pageButton()`, using `Heredoc`, in `classes/pagination.php`**

```php
function pageButtons($link,$page,$button_class,$mobile){
		return <<<HTML
		<a href="{$link}">
			<button type="button" class="btn btn-sm {$button_class} page-buttons">
				<span class="d-none d-lg-block">
					{$page}<!--page number-->
				</span>
				<span class="d-block d-lg-none font-weight-bold">
					{$mobile}<!--text to display on mobile view-->
				</span>
			</button>
		</a>
HTML;
	}
```

4.**And now the pagination code itself, also in `classes/pagination.php`**

**4.1**--First, we have `nextButtons()` which returns with the buttons that take us forward/to the next pages.

```php
function nextButtons($current_page,$all_pages,$page_diff,$next_link,$next_next_link,$last_link){
		if($all_pages>$current_page){
			if($page_diff>=1){
				echo $this->pageButtons($next_link,$current_page+1,"btn-outline-light",$current_page+1);
			}
			if($page_diff>=2){
				echo $this->pageButtons($next_next_link,$current_page+2,"btn-outline-light",$current_page+2);
			}
			if($page_diff>=1){
				echo $this->pageButtons($next_link,"Next","btn-outline-light","<i class='fas fa-angle-right'></i>");
			}
			if($page_diff>=3){
				echo $this->pageButtons($last_link,"Last","btn-outline-light","<i class='fas fa-angle-double-right'></i>");
			}
		}
	}
```

**Let me try to explain how it works exactly:**

```php
page_diff=all_pages-current_page

if($page_diff>=1)/*if the page difference is at least 1,
it means we can jump 1 page forward.
So a button which does so will be displayed.*/


all_pages=10;
$current_page=8--->10-8=2//✔
$current_page=9--->10-9=1//✔
$current_page=10--->10-10=0//✖




if($page_diff>=2)/*If the page difference is at least 2,
it means we can jump 2 pages ahead.
So a button that does so will be displayed too*/


all_pages=10;
$current_page=7--->10-7=3//✔
$current_page=8--->10-8=2//✔
$current_page=9--->10-9=1//✖




if($page_diff>=3)/*If the page difference is at least 3,
that means we can't jump to the last page with any of the buttons from above,
so one that leads there will be displayed as well.*/


all_pages=10;
$current_page=6--->10-6=4//✔
$current_page=7--->10-7=3//✔
$current_page=8--->10-8=2//✖
```
**4.2**--You can't tell it just from the picture, but in the center, which show the current page, **is actually a `select` Using that you can freely jump to any page you want.**

```php
function pageSelect($all_pages,$current_page,$page_link){
		?>
		<select class="form-control m-0 p-0 d-inline bg-transparent text-info border-info all-pages">
			<?php
			for ($i=1; $i < $all_pages+1; $i++) { 
				?>
				<option class="text-dark" <?php
				if($current_page==$i){
					echo "selected";
				}
				?> value="<?php
				echo $page_link.$i;
				?>">
					<?php
						echo $i;
					?>
				</option>
				<?php
			}
			?>
		</select>
		<?php
	}
```

**In short:** in the `value` attribute of the `options`, our current location(comments/)+number of page(`$i`) will be displayed.

For this to actually work, there is this small piece of `Jquery` code.

```javascript
$(".all-pages").on("change",function(){
        $(this).find("option").each(function(){
            if($(this).is(":selected")){
                location.href=$(this).attr("value");
            }
        });
    });
```

**4.3--And finally, we have some buttons to go back to a previous page, in function `prevButtons()`**

```php
function prevButtons($current_page,$prev_link,$prev_prev_link,$first_link){
		if($current_page>1){
			if(($current_page+1)-3>1){
				echo $this->pageButtons($first_link,"First","btn-outline-light","<i class='fas fa-angle-double-left'></i>");
			}
			if(($current_page+1)-1>1){
				echo $this->pageButtons($prev_link,"Prev","btn-outline-light","<i class='fas fa-angle-left'></i>");
			}
			if(($current_page+1)-2>1){
				echo $this->pageButtons($prev_prev_link,$current_page-2,"btn-outline-light",$current_page-2);
			}
			if(($current_page+1)-1>1){
				echo $this->pageButtons($prev_link,$current_page-1,"btn-outline-light",$current_page-1);
			}
		}
	}
```

**Now this is interesting, I'll try to explain it with examples**:

```php
/*we always add 1 to the current_page, to avoid 0 being the result,
that's how the code will work properly*/

//the formula looks something like this:
if((current_page+1)-pages_to_go_back>1)

/*the outcome/result must always be larger than 1*/

if(($current_page+1)-1>1)//Must be at least on the 2nd page, so that we can go back once.

$current_page=1---->(1+1)-1=1//✖
$current_page=2---->(2+1)-1=2//✔
$current_page=3---->(3+1)-1=3//✔



if(($current_page+1)-2>1)//Must be at least on the 3rd page, so that we can go back twice.

$current_page=2---->(2+1)-2=1//✖
$current_page=3---->(3+1)-2=2//✔
$current_page=4---->(4+1)-2=3//✔



if(($current_page+1)-3>1)/*Here 'pages_to_go_back' is 3,
because we go back at least 3 pages.
That means, we must be at least on the 4th page,
so that we can jump directly to the first page,
since if we are on the 3rd page,
a button which leads to the first page already exists(previous example).*/

$current_page=3---->(3+1)-3=1//✖
$current_page=4---->(4+1)-3=2//✔
$current_page=5---->(5+1)-3=3//✔

```

5.At last, let's go back to `index.php`, and add the following 3 lines of code.

```php
echo $pb->prevButtons($_GET['page'],$prev_link,$prev_prev_link,$first_link);
echo $pb->pageSelect($all_pages,$_GET['page'],$base_link);
echo $pb->nextButtons($_GET['page'],$all_pages,$page_diff,$next_link,$next_next_link,$last_link);
```

**And we're done.**

I've made a few changes from the original one, so I might have mistyped something.

I really hope I made sense most of the time, and you managed to understand how the code works. I know I couldn't explain everything well, but I tried my best. Let me know what you think about this solution, and the whole post itself.