Advanced Pagination (Tutorials » PHP)
Ever wonder how to make them nifty pagination links like on phpwned? Well now you can! Here is my tutorial on how to create some somewhat advanced pagination.
Pagination is a list of links to different pages of a result set.
We have our pagination function. Now all we need to do is find the number of rows in a result set, and the number of pages depending on how many results we want to show per page.
There are 2 decent ways of finding the number of rows in a result set. The best way is SQL_CALC_FOUND_ROWS, regardless of LIMIT in a query, it will calculate the number of rows in a search (including WHERE filtering). SQL_CALC_FOUND_ROWS is only available in MySQL 5 so if you are using an older version, you need to use another method or better yet, upgrade.
Another method is COUNT(*). This isn't as great because if you have any WHERE it will perform the search twice. This can have an adverse effect on performance especially if you are doing fulltext searching
But for this example I am going to use SQL_CALC_FOUND_ROWS because it is the best method. Also in this example we will make pagination for comments (showing 10 comments per page)
I hope this tutorial is useful. If you have any questions, comments, or suggestions, please register (it is fast, and of course free) and comment below.
Pagination is a list of links to different pages of a result set.
PHP Code:
<?php /** * The pagination function. Creates a list of links if multiple pages * @param int $pages : The number of pages * @param int $page : The current page number * @param int $show : The number of links in each direction (of the current page) to show * @param string $pre : What to prefix each link with (what comes before the page number) * @param string $post : What to suffix each link with (what comes after the page number) * @return string : The pagination */ function pagination($pages, $page, $show=2, $pre='?page=', $post='') { // $p is the output of the pagination function. Note the .= on future expressions regarding $p $p = 'Viewing page <b>'. $page .'</b> of <b>'. $pages .'</b>'; // only show pagination if there is more than one page if( $pages > 1 ) { // $first whether or not to show a link to the first page, and a "back" link $first = $page>1; // $last whether or not to show a link to the last page, and a "next" link $last = $page<$pages; // only link to previous page if there _is_ a previous page but show the text regardless $p .= '<br />'. ($first? '<a href="'. $pre . ($page-1) . $post .'" title="Go back a page (page '. ($page-1) .')">' : '') .'<b>‹</b>- Back'. ($first? '</a>' : '') .' '; // only _link_ to the first page if we arent already on the first page but show the text regardless $p .= ($first? '<a href="'. $pre . 1 . $post .'" title="Go to the first page">' : '') .'«'. ($first? '</a>' : ''); // the starting number of pages to show $min = $pages-$show-1; // the last page number to show $max = $pages+$show+1; // means that there are pages before the starting page we are showing so lets add ... to show this if( $min > 1 ) { $p .= ' ...'; } // make sure $min is at least 1 if( $min < 1 ) { $min = 1; } // make sure we dont show more pages than there are if( $max > $pages ) { $max = $pages; } // start $i at $min (the first page number to show) and end it when $i is > $max (after $i is greater than the last page to show) for( $i=$min; $i<=$max; $i++ ) { // set $b for reference to it the second time // if $i==$page means it is the current page so dont link it, instead make it bold with [] around it $p .= (($b=($i==$page))? ' <b>[' : ' <a href="'. $pre . $i . $post .'" title="Go to page '. $i .'">'). $i .($b? ']</b>' : '</a>'); } // means there are pages after the last page we are showing so lets add ... to show this if( $max < $pages ) { $p .= ' ...'; } // only _link_ it if we are not already on the last page but display the raquo regardless $p .= ($last? ' <a href="'. $pre . $pages . $post .'" title="Go to the last page (page '. $pages .')">' : ' ') .'»'. ($last? '</a>' : ''); // only _link_ to the next page if there _is_ a next page but show the text regardless $p .= ($last? ' <a href="'. $pre . ($page+1) . $post .'" title="Go to next (page '. ($page+1) .')">' : '') .'Next -<b>›</b>'. ($last? '</a>' : ''); } // return $p containing all the pagination. Wrap $p with whatever html container you need for styling etc for now lets just center the text return '<div style="text-align: center;">'. $p .'</div>'; } ?>
We have our pagination function. Now all we need to do is find the number of rows in a result set, and the number of pages depending on how many results we want to show per page.
There are 2 decent ways of finding the number of rows in a result set. The best way is SQL_CALC_FOUND_ROWS, regardless of LIMIT in a query, it will calculate the number of rows in a search (including WHERE filtering). SQL_CALC_FOUND_ROWS is only available in MySQL 5 so if you are using an older version, you need to use another method or better yet, upgrade.
PHP Code:
<?php // This would return up to 10 rows and only where page=5 $q = mysql_query("SELECT SQL_CALC_FOUND_ROWS id, name, comment FROM comments WHERE page=5 LIMIT 0, 10"); // to get the number of rows that SQL_CALC_FOUND_ROWS calculated, a second query is needed (needs to be the NEXT query after SQL_CALC_FOUND_ROWS) $rowcount = mysql_result(mysql_query("SELECT FOUND_ROWS()"), 0); ?>
Another method is COUNT(*). This isn't as great because if you have any WHERE it will perform the search twice. This can have an adverse effect on performance especially if you are doing fulltext searching
PHP Code:
<?php // get the roowcount $rowcount = mysql_result(mysql_query("SELECT COUNT(*) FROM comments WHERE page=5"), 0); // perform the query that actually fetches the data we want $q = mysql_query("SELECT id, name, comment FROM comments WHERE page=5 LIMIT 0, 10"); ?>
But for this example I am going to use SQL_CALC_FOUND_ROWS because it is the best method. Also in this example we will make pagination for comments (showing 10 comments per page)
PHP Code:
<?php // how many results per page $perpage = 10; // the current page to show $page = (int)$_GET['page']; // make sure $page is valid. If no page was specified default to 1 if( $page < 1 ) { $page = 1; } // $perpage * $page is a minimum of 10, rows start at 0, so subtract $perpage from from this number. $rowstart = ($perpage*$page)-$perpage; // perform our query $q = mysql_query("SELECT SQL_CALC_ROWS id, name, comment FROM comments WHERE page=5 LIMIT $rowstart, $perpage"); // get the rowcount. This is the total number of rows matching our WHERE $rowcount = mysql_result(mysql_query("SELECT FOUND_ROWS()"), 0); // only continue if there are any rows from the current page if( mysql_num_rows($q) ) { // the number of pages will be ceil() of $rowcount/$perpage. // ceil ALWAYS rounds UP. This is what we want, if there is only ONE result on the last page we still want it to be a page. you can read more at php.net/ceil $pages = ceil($rowcount/$perpage); // set $pagination to the return value of pagination so we can use it again as well as echo it. echo ($pagination = pagination($pages, $page)); // fetch each row from the result set while( ($f = mysql_fetch_array($q, MYSQL_ASSOC)) ) { // do what you need to do with each row } // display pagination at the end of the page too If you dont need to use it twice, just echo pagination() without storing it to $pagination above echo $pagination; } ?>
I hope this tutorial is useful. If you have any questions, comments, or suggestions, please register (it is fast, and of course free) and comment below.
Rate it
Leave a Comment
Login to leave comments.
User Comments