views:

109

answers:

4

I have a MySQL table holding lots of records that i want to give the user access to. I don't want to dump the entire table to the page so i need to break it up into 25 records at a time, so i need a page index. You have probably seen these on other pages, they kind of look like this at the base of the page:

< 1 2 3 4 5 6 7 8 9 >

For example, when the user clicks on the '4' link, the page refreshes and the offset is moved on (4th page x 25 records). Here is what i already have:

function CreatePageIndex($ItemsPerPage, $TotalNumberOfItems, $CurrentOffset, $URL, $URLArguments = array())
{
    foreach($URLArguments as $Key => $Value)
    {
     if($FirstIndexDone == false)
     {
      $URL .= sprintf("?%s=%s", $Key, $Value);
      $FirstIndexDone = true;
     }
     else
     {
      $URL .= sprintf("&%s=%s", $Key, $Value);
     }
    }

    Print("<div id=\"ResultsNavigation\">");
     Print("Page: ");
     Print("<span class=\"Links\">");
      $NumberOfPages = ceil($TotalNumberOfItems / $ItemsPerPage);
      for($x = 0; $x < $NumberOfPages; $x++)
      {
       if($x == $CurrentOffset / $ItemsPerPage)
       {
        Print("<span class=\"Selected\">".($x + 1)." </span>");
       }
       else
       {
        if(empty($URLArguments))
        {
         Print("<a href=\"".$URL."?Offset=".$x * $ItemsPerPage."\">".($x + 1)."</a> ");
        }
        else
        {
         Print("<a href=\"".$URL."&Offset=".$x * $ItemsPerPage."\">".($x + 1)."</a> ");
        }
       }
      }
      Print("</span>");
      Print(" (".$TotalNumberOfItems." results)");
    Print("</div>");
}

Obviously this piece of code does not create a dynamic index, it just dumps the whole index at the bottom of the page for every page available. What i need is a dynamic solution that only shows the previous 5 pages and next 5 pages (if they exist) along with a >> or something to move ahead 5 or so pages.

Anybody seen an elegant and reusable way of implementing this as i feel i'm re-inventing the wheel? Any help is appreciated.

A: 

How about this jQuery-plugin? So all the work is done on the clientside.

http://plugins.jquery.com/project/pagination

demo: http://d-scribe.de/webtools/jquery-pagination/demo/demo_options.htm

Natrium
+2  A: 

Zend Framework is becoming a useful collection and includes a Zend_Paginator class, which might be worth a look. Bit of a learning curve and might only be worth it if you want to invest the time in using other classes from the framework.

It's not too hard to roll your own though. Get a total count of records with a COUNT(*) query, then obtain a page of results with a LIMIT clause.

For example, if you want 20 items per page, page 1 would have LIMIT 0,20 while page 2 would be LIMIT 20,20, for example

$count=getTotalItemCount();
$pagesize=20;

$totalpages=ceil($count/$pagesize);

$currentpage=isset($_GET['pg'])?intval($_GET['pg']):1;
$currentpage=min(max($currentpage, 1),$totalpages);

$offset=($currentpage-1)*$pagesize;

$limit="LIMIT $offset,$pagesize";
Paul Dixon
and so does CodeIgniter: http://codeigniter.com/user_guide/libraries/pagination.html
Natrium
Yes, i'm currently using the LIMIT SQL keyword to currently limit the records returned, the result of which is then fed back into the function above.
Gary Willoughby
Then I wouldn't worry too much about re-inventing the wheel, you could spend more time searching for an existing implementation which wasn't quite right, or spend a few minutes crafting the required output!
Paul Dixon
A: 

It's called Pagination:

a few examples:

  1. A nice one without SQL
  2. A long tutorial
  3. Another tutorial
  4. And Another
  5. And of course.. google
Luis Melgratti
A: 

Heres an old class I dug out that I used to use in PHP. Now I handle most of it in Javascript. The object takes an array (that you are using to split the stack into pages) and return the current view. This can become tedious on giant tables so keep that in mind. I generally use it for paging through small data sets of under 1000 items. It can also optionally generate your jump menu for you.

class pagination {

function pageTotal($resultCount, $splitCount) {
 if (is_numeric($resultCount) && is_numeric($splitCount)) {
  if ($resultCount > $splitCount) {
   $pageAverage = (integer)$resultCount / $splitCount;
   $pageTotal = ceil($pageAverage);
   return $pageTotal;
  } else {
   return 1;
  }
 } else {
  return false;
 }
}

function pageTotalFromStack($resultArray, $splitCount) {
 if (is_numeric($splitCount) && is_array($resultStack)) {
  if (count($resultStack) > $splitCount) {
   $resultCount = count($resultStack);
   $pageAverage = (integer)$resultCount / $splitCount;
   $pageTotal = ceil($pageAverage);
   return $pageTotal;
  } else {
   return 1;
  }
 } else {
  return false;
 }
}

function makePaginationURL($preURL, $pageTotal, $selected=0, $linkAttr=0, $selectedAttr=0) {
 if (!empty($preURL) && $pageTotal >= 1) {
  $pageSeed = 1;
  $passFlag = 0;
  $regLink = '<a href="{url}&p={page}"';
   if (is_array($linkAttr)) $regLink .=  $this->setAttributes($linkAttr); //set attributes
  $regLink .= '>{page}</a>';

  $selLink = '<a href="{url}&p={page}"';
   if (is_array($selectedAttr)) $selLink .=  $this->setAttributes($selectedAttr); //set attributes
  $selLink .= '>{page}</a>';

  while($pageSeed <= $pageTotal) {
   if ($pageSeed == $selected) {
    $newPageLink = str_replace('{url}', $preURL, $selLink);
    $newPageLink = str_replace('{page}', $pageSeed, $newPageLink);
   } else {
    $newPageLink = str_replace('{url}', $preURL, $regLink);
    $newPageLink = str_replace('{page}', $pageSeed, $newPageLink);
   }
   if ($passFlag == 0) {
    $passFlag = 1;
    $linkStack = $newPageLink;
   } else {
    $linkStack .= ', ' . $newPageLink;
   }
   $pageSeed++;
  }
  return $linkStack;
 } else {
  return false;
 }
}

function splitPageArrayStack($stackArray, $chunkSize) {
 if (is_array($stackArray) && is_numeric($chunkSize)) {
  return $multiArray = array_chunk($stackArray, $chunkSize);
 } else {
  return false;
 }
}

}

Syntax