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
Related
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;
}
}
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.
I have an pagination code:
//pagination
$result1=$mysqli->query("SELECT * FROM product");
$row_per_page=10 ;
$rows=$result1->num_rows;
if ($rows>$row_per_page) $page=ceil($rows/$row_per_page);
else $page=1;
if(isset($_GET['start']) && (int)$_GET['start'])
$start=$_GET['start'];
else
$start=0;
$result=$mysqli->query("SELECT * FROM product limit $start,$row_per_page");
//End pagination
while ($rows = $result->fetch_assoc()) {
echo $rows['name'];
}
$page_cr=($start/$row_per_page)+1;
for($i=1;$i<=$page;$i++)
{
if ($page_cr!=$i) echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($i-1)."'>$i </a>"."</div>";
else echo "<div class='pagination'>".$i." "."</div>";
}
This code create pagination like this
Yeah, i want to remove 6 7 8 9 ect... and replace with "...". When i click to page 6, it will remove 1 2 3 4 5 - 10 11 12 13 etc..,it only show 6 7 8 9 as image below
[![Pagination][2]][2]
I hope you can understand my ideal, i try the best to show you.
Thank you so much
Here's a solution to your pagination problem, the kind of solution Google uses to paginate it's search results. Basically, the idea behind this solution is this:
At any point of time, at most 5 pagination links will be displayed i.e. from the current page's perspective, display two predecessor and successor pages. Let me explain this thing using two scenarios,
Case(1): When the number of pages is equal to or less than 5 (Lets say we have 4 pages)
In this case, we have to display all pagination links without any preceding or succeeding dots, like this:
// User is on page 1
1 2 3 4
- - -
// User is on page 3
1 2 3 4
- - -
// User is on page 4
1 2 3 4
- - -
Case(2): When the number of pages is greater than 5 (Lets say we have 10 pages)
In this case, we have to display both the pagination links and dots accordingly, like this:
// User is on page 1
1 2 3 4 5 ...
- - - -
// User is on page 5
... 3 4 5 6 7 ...
- - - -
// User is on page 10
... 6 7 8 9 10
- - - -
So after getting the current page number using $page_cr=($start/$row_per_page)+1;, the algorithm of this custom pagination system would be like this:
Check whether the number of pages is greater than 5 or not. If it's greater than 5, go to step 2 otherwise go to step 5.
Find the superset range of pages, like 1-10, or 1-20 etc. For example, if $page = 10 then this superset range would be 1-10. The code for this step is this:
// Superset range of pages
$superset_range = range(1, $page);
Find the subset range of pages to display, like 1-5, or 3-7 etc. For example, if $page = 10 then this subset range would be 1-5, or 3-7, or 6-10 etc., it can be any consecutive five page between 1 and 10. Also, adjust this range whenever necessary. The code for this step is this:
// Subset range of pages to display
$subset_range = range($page_cr - 2, $page_cr + 2);
// Adjust the range
foreach($subset_range as $p){
if($p <= 0){
array_shift($subset_range);
$subset_range[] = $subset_range[count($subset_range) - 1] + 1;
}elseif($p > $page){
array_pop($subset_range);
array_unshift($subset_range, $subset_range[0] - 1);
}
}
Display the pagination links and dots accordingly. The code for this step is this:
// Display pagination links and dots
if($subset_range[0] > $superset_range[0]){
echo "<div class='pagination'>... </div>";
}
foreach($subset_range as $p){
if($page_cr != $p){
echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($p-1)."'>$p </a>"."</div>";
}else{
echo "<div class='pagination'>".$p." "."</div>";
}
}
if($subset_range[count($subset_range) - 1] < $superset_range[count($superset_range) - 1]){
echo "<div class='pagination'> ...</div>";
}
Display all pagination links using your old code, like this:
// Display all page links
for($i = 1; $i <= $page; $i++){
if($page_cr != $i){
echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($i-1)."'>$i </a>"."</div>";
}else{
echo "<div class='pagination'>".$i." "."</div>";
}
}
So here's the complete code:
$result1 = $mysqli->query("SELECT * FROM product");
$row_per_page= 10;
$rows=$result1->num_rows;
if ($rows > $row_per_page){
$page=ceil($rows/$row_per_page);
}else{
$page=1;
}
if(isset($_GET['start']) && (int)$_GET['start']){
$start=$_GET['start'];
}else{
$start=0;
}
$result=$mysqli->query("SELECT * FROM product limit $start,$row_per_page");
while ($rows = $result->fetch_assoc()) {
echo $rows['name'];
}
$page_cr=($start / $row_per_page) + 1; // Page number
if($page > 5){
// From the current page's perspective, display two predecessor and successor pages
// Superset range of pages
$superset_range = range(1, $page);
// Subset range of pages to display
$subset_range = range($page_cr - 2, $page_cr + 2);
// Adjust the range
foreach($subset_range as $p){
if($p <= 0){
array_shift($subset_range);
$subset_range[] = $subset_range[count($subset_range) - 1] + 1;
}elseif($p > $page){
array_pop($subset_range);
array_unshift($subset_range, $subset_range[0] - 1);
}
}
// Display pagination links and dots
if($subset_range[0] > $superset_range[0]){
echo "<div class='pagination'>... </div>";
}
foreach($subset_range as $p){
if($page_cr != $p){
echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($p-1)."'>$p </a>"."</div>";
}else{
echo "<div class='pagination'>".$p." "."</div>";
}
}
if($subset_range[count($subset_range) - 1] < $superset_range[count($superset_range) - 1]){
echo "<div class='pagination'> ...</div>";
}
}else{
// Display all page links
for($i = 1; $i <= $page; $i++){
if($page_cr != $i){
echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($i-1)."'>$i </a>"."</div>";
}else{
echo "<div class='pagination'>".$i." "."</div>";
}
}
}
I recently ran into a problem with my pagination, it happens that there are like a 100 pages, so obviously my pagination becomes way to long.
Now I want to prevent this by removing some links, so instead of
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10
I want to show it as
1 - 2 - 3 - 4 - 5 - ... - 10
Or when you're on page 4
1 - ... - 4 - 5 - 6 - ... 10
At the moment the script that displays my pagination goes like this:
$links = array();
for($i = 0; $i < $totalPages; $i++) {
array_push($links, $i);
}
foreach($links as $pageLink) {
if($pageLink == $page) {
$pagination .= "<li><a href='" . BASE_URL . $url . $pageLink . ".html' class='active'>" . ($pageLink + 1) . "</a></li>";
} else {
if($pageLink === '...') {
$pagination .= "<li><a href='#'>...</a></li>";
} else {
$pagination .= "<li><a href='" . BASE_URL . $url . $pageLink . ".html'>" . ($pageLink + 1) . "</a></li>";
}
}
}
I added all the links in an array so it would be easy to adjust this, but I can't figure out how I can get the pagination like that.
Somehow you can get the current page number and the last page number. The pager item which represents your current page should be somewhat different from your other pages. If your page number is smaller or equal than 3 you show 1 2 3 ... LastPageNumber and if your current page is greater or equal than LastPageNumber - 2 then your paging should look like 1 ... 67 68 69. Otherwise your paging should look like 1 ... 30 31 32 33 34 ... 69 (in this example your current page is 32).
.
//Prev
.
for($number = 1; $number <= $num_pages; $number++)
{
if($page == $number)
{
$navigator .= "<b>[$number]</b> ";
}
else
{
$navigator .= "<a href='?c=".$_SESSION['cID']".&rows=".$per_page."&page=$number'>$number</a> ";
}
}
.
//Next
.
This is the snippet that prints number of pages.
Sample output:
Previous 1 2 3 4 [5] 6 7 8 9 10 Next
5 is the current page.
Problem: page numbers are shown in sequence with no restrictions. If i have 100 pages, all numbers show up.
Question: I need my paging numbers appear as the following...
Assume we only have 7 ($num_pages) pages:
Previous 1 2 [3] 4 5 6 7 Next
Assume we have 90 pages:
[1] 2 3 4 5 6 7 ... 90 Next
Assume user clicked the 7th page:
Previous 1 ... 5 6 [7] 8 9 10 11 ... 90 Next
Assume user clicked 11th page:
Previous 1 ... 9 10 [11] 12 13 14 15 ... 90 Next
Assume user clicked 15th page:
Previous 1 ... 13 14 [15] 16 17 18 19 ... 90 Next
Assume user clicked 90th page:
Previous 1 ... 84 85 86 87 88 89 [90]
Any help will be appreciated.
$radius = 3;
for($i = 1; $i <= $total; $i++){
if(($i >= 1 && $i <= $radius) || ($i > $current - $radius && $i < $current + $radius) || ($i <= $total && $i > $total - $radius)){
if($i == $current) echo "<b>".$i."</b>";
}
elseif($i == $current - $radius || $i == $current + $radius) {
echo "... ";
}
}
This should be more than enough to get you started at least
$count = 7; // number to show
// start at half threshold down from the current location.
$number = $current - round($count/2);
if( $number > 1 ) echo '...';
else $ // increase to have number start at 1.
for( $number; $number < $number + $count; $number++)
{
// your for loop as normal
}
if( $number < $total ) echo '...';
An elegant solution for this kind of thing is to use "logarithmic page navigation". See my answer to this question (PHP code included):
How to do page navigation for many, many pages? Logarithmic page navigation