How to build a pagination with ellipsis - php

so, I read every related questions here but they were not what Im asking here so please if you feel this question is a duplicate consider some one new to PHP asking this who can't find any good answer and I'm also asking please do not down vote this maybe some one wants to help me. Thanks
btw this is my code for pagination:
<?php
$per_page = 10;
if(isset($_GET['page'])){
$page = $_GET['page'];
} else {
$page = 1;
}
if($page == "" || $page == 1) {
$page_1 = 0;
} else {
$page_1 = ($page * $per_page) - $per_page;
}
$item_count = "SELECT * FROM products";
$find_count = mysqli_query($connection, $item_count);
$count = mysqli_num_rows($find_count);
$count_pages = ceil($count / $per_page) ;
?>
<ul class="pagination">
<?php
for($i = 1; $i <= $count_pages; $i++){
if($i == $page) {
echo "<li><a class='active-page' href='./latest.php?page=$i'>$i</a></li>";
} else {
echo "<li><a href='./latest.php?page=$i'>$i</a></li>";
}
}
?>
</ul>
the code get the page number with a Get request and do a loop for number of pages. and pagination out put is like this :
1 2 3 4 5 6 7 8 9 10
but I dont want to display like above, I want to make this shorter with "..." , like this if the user is on page 3:
1 2 3 4 5 ... 9 10
or user is on page 9 :
1 2 ... 7 8 9 10
how can I manipulate this code to achieve this?

Hey there The Big Ash!
You're almost there already. You just need to check a couple of things:
is $i within two pages of the beginning or the end of the page count. That's easy, right?
if ($i <= 2 || $i >= $count_pages - 2)
is $i within two pages of the current page?
This is achieved with
if (abs($i - $page) <= 2)
So now the question remains: when to put the ellipsis?
If you just echo '...' every time the above conditions are not met, you'll just end up with a whole bunch of ellipses, right?
Also, it's possible that you'll need two ellipses (imagine there are 20 pages and you're on page 10. You'd want '1 2 ... 8 9 10 11 12 ... 19 20).
I'm sure there's a more elegant way to this, but I'd just use a flag ($outOfRange) which is set to false when any of the above conditions are met, but set to true when they are not. Then we echo '...' only when the conditions are not met but $outOfRange is still false. So we have:
$outOfRange = false;
for($i = 1; $i <= $count_pages; $i++) {
if ($i <= 2 || $i >= $count_pages - 2 || abs($i - $page) <= 2) {
// page number should be echoed so do as you did before
$outOfRange = false;
if($i == $page) {
echo "<li><a class='active-page' href='./latest.php?page=$i'>$i</a></li>";
} else {
echo "<li><a href='./latest.php?page=$i'>$i</a></li>";
}
} else {
// we are out of range! if not already out of range, echo ellipsis
if (!$outOfRange) {
echo ' ... ';
}
$outOfRange = true;
}
}

Related

Get numbers next and after a certain number with dynamic max results with PHP

I have a pagination which renders some pages. I have a setting where the user can define how many pages are to be displayed as numbers in the pagination nav. The first and last number are always visible. Now if the user wants to have 3 numbers on the nav and assuming that i am now in the page 7, then it should look like this:
1 ... 6 7 8 ... 12
If the user wants four items then it should look like that:
1 ... 6 7 8 9 ... 12
Up until now i have the following which gives me 3 before and after the current page
$maxLinks = 3;
$currentPageNumber = 7;
$pages = [];
$pages[] = 1;
for($i = max(2, $currentPageNumber - $maxLinks); $i <= min($currentPageNumber + $maxLinks, 12 - 1); $i++) {
$pages[] = $i;
}
$pages[] = 12;
foreach ($pages as $key => $page) {
$newPage = '...';
if (($key === 0) && $pages[1] !== $page + 1) {
array_splice( $pages, 1, 0, $newPage );
}
$itemBeforeLast = count($pages)-2;
if (is_numeric($pages[$itemBeforeLast]) && ($key === $itemBeforeLast) && $pages[$itemBeforeLast + 1] !== $pages[$itemBeforeLast] + 1) {
array_splice( $pages, $itemBeforeLast +1, 0, $newPage );
}
}
This gives me back the following:
But i only want to get 3 or 4 numbers between the dots (this changes based on the value that the user gives in the settings ($maxLinks variable))
Any help is deeply appreciated
Best regards
As you add them to both sides, you need to divide by 2. Also, remove 1 to account for the current page. Then you just need to account for the possibility of having a non-even number of links to the left&right by rounding (down for the left, up for the right).
And end up with:
for($i = max(2, $currentPageNumber - floor(($maxLinks-1)/2));
$i <= min($currentPageNumber + ceil(($maxLinks-1)/2), 12 - 1); $i++)

Pagination, for loop

I'm trying to make a pagination where I can limit how many numbers it will show in the navigation so it will be something like this
< 1 ... [3] 4 5 ... 9 >
The script I have now is working fine until I'm at the last couple of pages. Lets say I set max numbers allowed in the navigation to 4 and number of pages to 9. Then it will work to page 7, but from page 7 it will start shrink in numbers and not put them in front of the current page number. It will behave like this
< 1 ... [7] 8 9
< 1 ... [8] 9
When I'm at the last page the navigation will only show
< 1 ... 9
What i would like it to look like is like this
< 1 ... 6 [7] 8 9 >
< 1 ... 6 7 [8] 9 >
< 1 ... 6 7 8 [9]
I have tried to make this work for some hours now but, are kind of stuck. Any suggestions?
// Method to output the pagination
function output_pagination($max_per_page, $table) {
$page_number = $this->valid_page_number($this->get_page_number(), $table); // Get current page number
$num_pages = $this->count_table_rows($table) / $max_per_page; // Set the number of pages
$max_nav_pages = 4; // Max numbers of pages in the page navigation
$start = $page_number-1; // Value to start the loop on
// Set start to 1 if it equals 0
if($start === 0) {
$start = 1;
}
// Keep loop going until $i no longer is greater or equal to number of pages
for($i = $start; $i <= $num_pages; $i++) {
// Output prev arrow + '...' + 1 if its the start of the pagination and page number not equals 1 ($i = 1 and page number is > $i)
if(($i === $start) && ($page_number > 1)) {
// Check if number of pages are greater then max allowed in navigation and if page number not equals 2
if(($num_pages > $max_nav_pages) && ($page_number !== 2)) {
echo "<< ";
echo "< ";
echo "1 ";
echo " ... ";
$i = $page_number - 1;
} else {
echo "<< ";
echo "< ";
echo $i;
}
}
// Output current page in bold text if $i equals or are greater then $start and page number equals $i
else if (($i >= $start) && ($page_number === $i)) {
echo " <b>[".$i."]</b> ";
}
// Output "...", last page number and next page arrow. if we have 10 pages or more. Then break the loop. We are done.
else if($i === $start + $max_nav_pages) {
// Check if page number equals number of pages - max allowed nav pages + 1
if($page_number === $num_pages-$max_nav_pages+1) {
echo $i;
echo " >";
echo " >>";
break;
} else {
echo " ... ";
echo $num_pages;
echo " >";
echo " >>";
break;
}
}
// Output next page number if $i is greater then $start and $i + 1 is equal or greater then number of total pages
else if(($i > $start) && ($i + 1 <= $num_pages)) {
echo " ".$i." ";
}
else { // Output last page number and next page arrow. We are done.
echo $i;
echo " >";
echo " >>";
}
}
}
Let's say you are in page 8, then the loop always starts from $page_number - 1 which will be 7, which means 6 will never be displayed. You need to start your loop from $page_number - $max_nav_pages and determine which numbers should be displayed that way.

All Pagination numbers are displaying using PHP and Mysql

I am fetching username and Id from the database. I have more than 500 usernames. I have to display pagination number only 1 to 5 and last pagination number.
Example:- pagination number is:- 1 2 3 4 5...20(last number).
Now I am getting all numbers in horizontal. Would you help me in this?
Can anyone help me with NEXT and LAST in pagination?
include('../db/connection.php');
$reclimit = 3;
if(isset($_GET['page'])){
$page = $_GET['page'];
} else {
$page = 1;
}
$start = (($page-1) * $reclimit);
$sql = "SELECT * FROM request";
$records =$conn->query($sql);;
$total = $records->num_rows;
$tpages = ceil($total / $reclimit);
$search_sql="SELECT * FROM request LIMIT ".$start."," .$reclimit;
$search_result = $conn->query($search_sql);
HTML
<body>
<?php
if (isset($search_result->num_rows) > 0) {
?>
<h2 class="result-title">Results matching your need</h2>
<?php
while($search_ok = $search_result->fetch_assoc()) {
$user_id=$search_ok['Id'];
$user_name=$search_ok['Name'];
echo "
<div class='search-section'>
<div class='search-profile'>
<div class='s_user_id'>{$user_id}</div>
<div class='s_user_name'>{$user_name}</div>
</div>
</div>
";
}}
for($i=1;$i<=$tpages;$i++) {
echo "".$i."";
}
?>
</body>
The pagination which you are using is simple and working one. But the pagination which you are searching is smart way and you should achieve this by using some if conditions. Similar answer are there in SO. Go to the following, this may help you
Smart pagination algorithm
PHP pagination
Limit pagination page number
It's a simple idea, but I didn't test it. Edit foreach displaying numbers:
$pgStart = 1;
if (isset($_GET['page'])) { // get first showing number = current page - 2
$pg = $_GET['page'] - 2;
$pgStart = $pg + 5 > $tpages ? $tpages - 4 : $pg; //EDIT fix when reach pages end
$pgStart = $pg < 1 ? 1 : $pg; // This must be after ending correction (previous line)
}
if ($pgStart > 1) { // show 1
echo '1 ... ';
}
for($i = $pgStart; $i <= $tpages && $i < $pgStart + 5; $i++) { // show 5 pages
echo ' '.$i.' ';
}
if ($i < $tpages) { // show last
echo ' ... '.$tpages.'';
}
EDIT
Output of this script with $_GET['page'] = 7 and $tpages = 20 from php sandbox is (without linebreaks):
1 ...
5
6
7
8
9
... 20

PHP Pagination - Limit amount of links

So i have my pagination links like this.
for ( $counter = 0; $counter <= $page_amount; $counter += 1) {
echo "<a href=\"section.php?q=$section&p=$counter\">";
echo $counter+1;
echo "</a>";
}
And the links grows like:
1 2 3 4 5 6 7 and so on.
But i want to limit this so if there is more than 7 pages it shall only show 7 links like this:
1 2 3 ... 10 11 12
where 12 is the last page.
And if you go to next page it will only change the first pages like this:
3 4 5 ... 10 11 12
until you reach the last 7 pages like this:
6 7 8 9 10 11 12
How do i do this ??
please help.
Here is one way to do it.
// Set some presets
$current_page = 0;
$page_amount = 11;
$limiter = 7;
// Set upper and lower number of links
$sides = round(($limiter/2), 0, PHP_ROUND_HALF_DOWN);
for ( $counter = 0; $counter <= $page_amount; $counter++) {
// Start with Current Page
if($counter >= ($current_page)){
// Show page links of upper and lower
if(($counter <($current_page+$sides))||($counter >($page_amount-$sides))){
echo "<a href=\"section.php?q=$section&p=$counter\">";
echo $counter+1;
echo "</a> ";
}
// The middle link
elseif($counter ==($current_page+$sides)){
echo "<a href=\"page.php?p=$counter\">";
// Show number if number of links == $limiter
if(($page_amount-$current_page)==$limiter-1){
echo $counter+1;
}
// Show '...' number of links > $limiter
else {
echo "...";
}
echo "</a> ";
}
}
}
This allows to change the number of links shown, ie. from 7 to 9.
Note, using PHP_ROUND_HALF_DOWN in round() requires php>=5.3

How can I limit the page numbers shown in the pagination?

I am trying to limit the shown pagination. My site has 500+ pages, and all 500+ numbers are shown in the pagination.
I am trying to limit it like this:
Prev 1 2 3 4 5 6 Next
My code:
$skin = new skin('site/pagination'); $pagination = '';
if ($pages >= 1 && $page <= $pages) {
for ($x=1; $x<=$pages; $x++) {
$TMPL['pagination'] = ($x == $page) ? '<strong>'.$x.'</strong> ' : ''.$x.' ';
$pagination .= $skin->make();
}
}
pagination page number limit problem solve by chnage
for ($x=1; $x<=$pages; $x++)
to
for($x = max(1, $page - 5); $x <= min($page + 5, $pages); $x++)
What do you expect this to do?:
for ($x=1; $x<=$pages; $x++)
It is going to create an entry for every page. If you don't want that, limit it how it makes sense:
for ($x=1; $x <= min(5, $pages); $x++)
Even better would be to consider the current page:
for ($x=max($curpage-5, 1); $x<=max(1, min($pages,$curpage+5)); $x++)
//Let's say you want 3 pages on either side of your current page:
$skin = new skin('site/pagination'); $pagination = '';
$currentPage = get the current page number however you have it stored;
// set the lower bound as 3 from the current page
$fromPage = $currentPage - 3;
// bounds check that you're not calling for 0 or negative number pages
if($fromPage < 1) {
$fromPage = 1;
}
// set the upper bound for what you want
$toPage = $fromPage + 7; // 7 is how many pages you'd like shown
// check that it doesn't exceed the maximum number of pages you have
if($toPage > $maxPages) {
$toPage = $maxPages;
}
// iterate over your range
for ($x=$fromPage; $x<=$toPage; $x++) {
$TMPL['pagination'] = ($x == $page) ? '<strong>'.$x.'</strong> ' : ''.$x.' ';
$pagination .= $skin->make();
}
For large numbers of pages, consider displaying links using "logarithmic" pagination. See my answer here (PHP code included):
How to do page navigation for many, many pages? Logarithmic page navigation
I tried the answers provided by wallyk and Hemang but they fell short for my pagination case. Their answers would sometimes display less links than the range. I had to add some max and min statements.
Here is my take in Javascript code:
var minPage = Math.max(Math.min(currentPage - (range / 2), totalPages - range), 0);
var maxPage = Math.min(Math.max(currentPage + (range / 2), range), totalPages);
The range is the number of links always displayed.
The totalPages is the total number of pages to iterate over.
The currentPage is the currently displayed page.
Note that my pagination index is 0 based.

Categories