Page Numbering: how do you get the ... between them?

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Page Numbering: how do you get the ... between them?

Post by simonmlewis »

I have a set of around 24 pages of content, and rather than 24 links, plus the Next, Last etc, it would be good to know how to make it like so:

First, Prev, 1, 2, 3, 4, 5 ...... 20, 21, 22, 23, 24, Next, Last

Do you have to literally put dots in the code, and tell it not to display the DIV if the number == 6, 7... and so on?
Though if you did, it would NEVER show.
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Page Numbering: how do you get the ... between them?

Post by simonmlewis »

This is how the code is set now.

Code: Select all

$maxPage = ceil($numrows/$rowsPerPage);
 
// print the link to access each page
$self = $_SERVER['PHP_SELF'];
$nav  = '';
 
for($page = 1; $page <= $maxPage; $page++)
{
   if ($page == $pageNum)
   {
      $nav .= " $page "; // no need to create a link to current page
   }
   else
   {
      $nav .= " <a href=\"/accessories/page/$page/\" class='pagelink'>$page</a>";
   }
}
 
// creating previous and next link
// plus the link to go straight to
// the first and last page
 
if ($pageNum > 1)
{
   $page  = $pageNum - 1;
   $prev  = " <a href=\"/accessories/page/$page/\" class='pagelink'>[Prev]</a> ";
 
   $first = " <a href=\"/accessories\" class='pagelink'>[First Page]</a>";
}
else
{
   $prev  = '&nbsp;'; // we're on page one, don't print previous link
   $first = '&nbsp;'; // nor the first page link
}
 
if ($pageNum < $maxPage)
{
   $page = $pageNum + 1;
   $next = " <a href=\"/accessories/page/$page/\" class='pagelink'>[Next]</a>";
 
   $last = " <a href=\"/accessories/page/$maxPage/\" class='pagelink'>[Last Page]</a>";
}
else
{
   $next = '&nbsp;'; // we're on the last page, don't print next link
   $last = '&nbsp;'; // nor the last page link
}
 
// print the navigation link
echo "</div><div class='navpages'>" . $first . $prev . $nav . $next . $last . "</div>";
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Page Numbering: how do you get the ... between them?

Post by Celauran »

Rather than iterating over the complete set, you could iterate twice; once from page 1 to, say, 5, then again from $maxPage - 5 to $maxPage. Insert your dots in between.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Page Numbering: how do you get the ... between them?

Post by simonmlewis »

I'm not exactly sure how you mean.

You obviously mean in this bit of code. I need to make it do it only if there are x amount of pages though. Though I guess that bit is easy.

Code: Select all

for($page = 1; $page <= $maxPage; $page++)
{
   if ($page == $pageNum)
   {
      $nav .= " $page "; // no need to create a link to current page
   }
   else
   {
      $nav .= " <a href=\"/airsoft-accessories/page/$page/\" class='pagelink'>$page</a>";
   }
}
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Page Numbering: how do you get the ... between them?

Post by Celauran »

Using that bit of code you posted, and assuming you wanted to display the first 5 ... last 5 links, you could do something like this:

Code: Select all

<?php

if ($maxPage <= 10) {
    for($page = 1; $page <= $maxPage; $page++)
    {
       if ($page == $pageNum)
       {
          $nav .= " $page "; // no need to create a link to current page
       }
       else
       {
          $nav .= " <a href=\"/airsoft-accessories/page/$page/\" class='pagelink'>$page</a>";
       }
    }
} else {
    for ($page = 1; $page <= 5; $page++) {
       if ($page == $pageNum)
       {
          $nav .= " $page "; // no need to create a link to current page
       }
       else
       {
          $nav .= " <a href=\"/airsoft-accessories/page/$page/\" class='pagelink'>$page</a>";
       }    
    }
    $nav .= "...";
    for ($page = $maxPage - 5; $page <= $maxPage; $page++) {
       if ($page == $pageNum)
       {
          $nav .= " $page "; // no need to create a link to current page
       }
       else
       {
          $nav .= " <a href=\"/airsoft-accessories/page/$page/\" class='pagelink'>$page</a>";
       }    
    }
}
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Page Numbering: how do you get the ... between them?

Post by Celauran »

That is, admittedly, a little over simplified as you'd need to account for situations where the current page falls within that middle range (say you're on page 11 of 26), but that's the general idea.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Page Numbering: how do you get the ... between them?

Post by Celauran »

What I'll typically do, though, is use a range of X pages centered on the current page, along with first, previous, next, and last buttons.
[text]<< < 3 4 5 6 7 8 9 > >>[/text]
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Page Numbering: how do you get the ... between them?

Post by simonmlewis »

Yes I see the issue with the page number within the dots - and just came a cropper with that!
So how would I do it with the range of X Pages. As I could easily just add on the page "total page: 15" at the end.
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Page Numbering: how do you get the ... between them?

Post by Celauran »

This is a simple paginator I wrote quite a while ago. I had to modify it slightly to not rely on other classes (models, requests, etc) so it might not be 100% perfect, but it should do what you need.

Code: Select all

<?php

class Paginator {

    protected $page;
    protected $per_page;
    protected $results;

    /**
     * @param (int) $results   The total number of entities in the result set
     * @param (int) $per_page  Number of items to display on a page
     */
    public function __construct($results, $per_page = 10) {
        $this->page = 1;
        $this->per_page = $per_page;
        $this->results = $results;
    }

    public function getPage() {
        return $this->page;
    }

    public function setPage($page) {
        $this->page = (int) $page;
    }

    /**
     * @return (int) Total number of pages
     */
    public function getPageCount() {
        return ceil($this->results / $this->per_page);
    }

    /**
     * @param (int) $count Number of pages to display in paginator
     */
    public function getPageNumbers($count) {
        $numbers = array();

        if ($this->page < ceil($count / 2)) {
            for ($i = 1; $i <= $count; $i++) {
                $numbers[] = $i;
            }
        } else if (($this->getPageCount() - $this->page) < ceil($count / 2)) {
            for ($i = $this->getPageCount() - ($count - 1); $i <= $this->getPageCount(); $i++) {
                $numbers[] = $i;
            }
        } else {
            for ($i = $this->page - (floor($count / 2)); $i <= $this->page + (floor($count / 2)); $i++) {
                $numbers[] = $i;
            }
        }

        return $numbers;
    }

    /**
     * @param (int) $count  Number of pages to display in the paginator
     *
     * @return (array)  Array containing first, previous, ..., next, last pages
     */
    public function getPagesForDisplay($count = 7) {
        $pages = array(
            'first' => 1,
            'last' => $this->getPageCount(),
        );

        if ($this->page > 1) {
            $pages['previous'] = $this->page - 1;
        }

        $pages['numbers'] = $this->getPageNumbers($count);

        if ($this->page < $this->getPageCount()) {
            $pages['next'] = $this->page + 1;
        }

        return $pages;
    }
}
Pass your row count to the paginator, and optionally the number of items you'd like per page. The getPagesForDisplay method will return the specified number of pages (defaults to 7) centered around the current page (which you can set via setPage method)
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Page Numbering: how do you get the ... between them?

Post by simonmlewis »

Sorry, but I wish I had the knowledge to understand what you have written there, as well as to integrate that into my code.

I have seen code that has the dots, like you did earlier, and then still shows the page that you are on. That would be better. Tho it might vbe a combination of the two.
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Page Numbering: how do you get the ... between them?

Post by Celauran »

It's really quite simple. Something like this should do, but use it or don't, as you wish.

Code: Select all

<?php
...
$results = mysql_num_rows($result); // or similar
$paginator = new Paginator($results);
$pages = $paginator->getPagesForDisplay();
...
?>
<ul id="paginator">
    <?php if (isset($pages['first'])): ?>
        <li><a href="/some/page/here/<?= $pages['first']; ?>">&laquo;</a></li>
    <?php endif; ?>

    <?php if (isset($pages['previous'])): ?>
        <li><a href="/some/page/here/<?= $pages['previous']; ?>">&lsaquo;</a></li>
    <?php endif; ?>

    <?php foreach ($pages['numbers'] as $page): ?>
        <?php if ($page == $paginator->getPage()): ?>
            <li><?php echo $page; ?></li>
        <?php else: ?>
            <li><a href="/some/page/here/<?= $page; ?>"><?php echo $page; ?></a></li>
        <?php endif; ?>
    <?php endforeach; ?>

    <?php if (isset($pages['next'])): ?>
        <li><a href="/some/page/here/<?= $pages['next']; ?>">&rsaquo;</a></li>
    <?php endif; ?>

    <?php if (isset($pages['last'])): ?>
        <li><a href="/some/page/here/<?= $pages['last']; ?>">&raquo;</a></li>
    <?php endif; ?>
</ul>
Post Reply