0

I have a pagination script which I have posted below, the problem is I have alot of data so I end with a huge list of pages, I want to make it show only 10 pages at a time and then maybe the last 2 pages like this:

previous 1 2 3 4 5 6 7 8 9...24 25 next

is there anyway I can change the code to do this. Below is the included pagination script I can include the other part of script if needed.

<?php
//source unknown for logic of showPageNumbers()
//modified by drale.com - 1-19-2010
//added query_string reproduction and divs
//added showNext() and showPrev()

class Pagination 
{
    function getStartRow($page,$limit)
    {
        $startrow = $page * $limit - ($limit);
        return $startrow;
    }

    function showPageNumbers($totalrows,$page,$limit)
    {
        $query_string = $this->queryString();
        $pagination_links = null;

        /*
         * PAGINATION SCRIPT
         * seperates the list into pages
         */     
        $numofpages = $totalrows / $limit; 
        /* We divide our total amount of rows (for example 102) by the limit (25). This 
           will yield 4.08, which we can round down to 4. In the next few lines, we'll
           create 4 pages, and then check to see if we have extra rows remaining for 
           a 5th page. */

        for ($i = 1; $i <= $numofpages; $i++) {
            /* This for loop will add 1 to $i at the end of each pass until $i 
               is greater than $numofpages (4.08). */       
            if ($i == $page) {
                $pagination_links .= '<div class="page-link"><span>' . $i 
                                   . '</span></div> ';
            } else { 
                $pagination_links .= '<div class="page-link"><a href="?page=' . $i 
                    . '&' . $query_string . '">' . $i . '</a></div> '; 
            }

            /* This if statement will not make the current page number available 
               in link form. It will, however, make all other pages available 
               in link form. */
        }   // This ends the for loop

        if (($totalrows % $limit) != 0) {
        /* The above statement is the key to knowing if there are remainders, and it's 
        all because of the %. In PHP, C++, and other languages, the % is known as a 
        Modulus. It returns the remainder after dividing two numbers. If there is no 
        remainder, it returns zero. In our example, it will return 0.8 */

            if ($i == $page) {
                $pagination_links .= '<div class="page-link"><span>' . $i 
                                   . '</span></div> ';
            } else {
                $pagination_links .= '<div class="page-link"><a href="?page=' . $i 
                    . '&'.$query_string.'">'.$i.'</a></div> ';
            }
            /* This is the exact statement that turns pages into link 
               form that is used above */ 
        } // Ends the if statement 

        return $pagination_links;
    }

    //added by drale.com - 1-19-2010
    function showNext($totalrows,$page,$limit,$text="next &raquo;")
    {
        $next_link = null;
        $numofpages = $totalrows / $limit;

        if ($page < $numofpages) {
            $page++;
            $next_link = '<div class="page-link"><a href="?page=' . $page 
                       . '&'.$query_string.'">' . $text . '</a></div>';
        }

        return $next_link;
    }

    function showPrev($totalrows,$page,$limit,$text="&laquo; prev")
    {
        $next_link = null;
        $numofpages = $totalrows / $limit;

        if ($page > 1) {
            $page--;
            $prev_link = '<div class="page-link"><a href="?page=' . $page 
                . '&' . $query_string . '">'.$text.'</a></div>';
        }

        return $prev_link;
    }

    function queryString()
    {
        //matches up to 10 digits in page number
        $query_string = eregi_replace("page=[0-9]{0,10}&","",$_SERVER['QUERY_STRING']);
        return $query_string;
    }
} 
?>
Rizvi
  • 289
  • 2
  • 14
james
  • 25
  • 1
  • 3
  • 1
    I'm afraid there is a little more to it than that. For instance, how do you want it to behave when you are on page 15 of 25, should you cut out a few pages both at the beginning and at the end, or how do you want it to work? – Christofer Eliasson Nov 06 '11 at 10:36
  • sorry i forget about that, if you are on page 15 cut off some at the begining so it would like: previous 7 8 9 10 11 12 13 14 15..24 25 next. thanks – james Nov 06 '11 at 10:43

2 Answers2

1

Untested, but this should always show pages 1 - 3 and the last 3 pages of the list. Otherwise, it will only ever show the previous 3 pages and the next three pages from the current one you're on. (whenever the amount of pages is greater than 10)

$alwaysShowPages = array(1, 2, 3);

// dynamically add last 3 pages
for ($i = 3; $i >= 0; $i--) {
    $alwaysShowPages[] = $numofpages - $i;
}

for ($i = 1; $i <= $numofpages; $i++) {
    $showPageLink = true;

    if ($numofpages > 10 && !in_array($i, $alwaysShowPages)) {
        if (($i < $page && ($page - $i) > 3)
            || ($i > $page && ($i - $page) > 3)
        ) {
            $showPageLink = false;
        }
    }

    if ($showPageLink) {
        if ($i == $page) {
            $pagination_links .= '<div class="page-link"><span>'.$i.'</span></div> ';
        } else { 
            $pagination_links .= '<div class="page-link"><a href="?page='.$i.'&'.$query_string.'">'.$i.'</a></div> '; 
        }
    }
}
Yes Barry
  • 8,896
  • 4
  • 43
  • 63
  • This solution wouldn't give him exactly what he requested in his clarifying comment, however I believe this solution is more useful from a user perspective. – Christofer Eliasson Nov 06 '11 at 11:16
  • thanks guys, this isn't exactly what I wanted but I think it will work better this way. is there a way to stop it from always showing the first 3 pages and just show the 3 before and after. Thanks – james Nov 06 '11 at 11:37
  • 1
    assuming one of the $alwaysShowPages is the current page, just use something like this: for($i = $currentPage -3; $i <= $currentPage +3;$i++) { $alwaysShowPages[] = $i; } And of course if you need to get rid of duplicates: $alwaysShowPages = array_unique($alwaysShowPages); – Buttle Butkus Nov 06 '11 at 13:41
  • Yeah he's right, my method is far from perfect but it'll do the trick quick-and-dirty style at least. – Yes Barry Nov 06 '11 at 17:21
0

I have a version that does this:

1 | 2 | 3 | 4 | 5 | 6 ... 554 | 555 | 556

1 | 2 | 3 | 4 | 5 | 6 ... 554 | 555 | 556

1 | 2 | 3 ... 278 | 279 | 280 ... 554 | 555 | 556

1 | 2 | 3 ... 415 | 416 | 417 ... 554 | 555 | 556

1 | 2 | 3 | 553 | 554 | 555 | 556

The ... are actually links that go halfway between current page and 1st of the next (or last) group of links.

I made it so the 1st 6 pages always appear if current page is less than 5.

But I made all parameters dynamic, so you can change variables like: $end_links = 3; // set number of links at each end to always show $center_links; // number of links including current page to show 'floating' in center

It took me hours to do it, which is pretty sad. Oh well.

Just use arrays a lot, and figure out how to add the right values to it. It's simple math and logic, really.

Buttle Butkus
  • 8,409
  • 13
  • 73
  • 110
  • For that many pages, a "logarithmic" page navigation scheme would be more appropriate. [See here](http://stackoverflow.com/q/7835752/999120). – Doin Jan 07 '13 at 15:23
  • Your answer seems to have way too many links though. My method definitely needs some tweaking. But the result I was trying to achieve is mimic the most efficient process for guessing a number between 1 and n one step at a time. 1st you guess n/2. Then you guess either n/2 + n/4 or n/2 - n/4. Then n/2 +/- n/4 +/- n/8. Etc. "Butterfly" method. – Buttle Butkus Jan 08 '13 at 01:03
  • Buttle, look at your first line: How do you get to p.200? For a "butterfly" method, you need minimum 5 links: Assuming _n_ pages, and current page = _p_, links required are _1, p/2, p, (p+n)/2, n_. But that's not what users are expecting from pagination links, and would probably confuse most people, who are expecting to be shown a _range_ of links to choose from. My method provides both a range, and the ability to "butterfly" select (as you put it). – Doin Jan 09 '13 at 08:46
  • Buttle, you could certainly tweak my method to show fewer links. One way might be to change from powers-of-10 to powers-of-2 (for example). But the simplest way might be to "densify" the links only around the current page, and not around the endpoints. I might consider adding that option to my code! Note also that my method does show fewer links when there are fewer total pages, of course! – Doin Jan 09 '13 at 08:50