Dynamic Pagination
More validation can be applied when handling default values. I am not a fan of outputing anything directly from a class, I prefer to return the links as an array. It's easier to maintain. This way, when/if you change the styling; then it saves having to trawl through your classes.<?phpclass...
More validation can be applied when handling default values. I am not a fan of outputing anything directly from a class, I prefer to return the links as an array. It's easier to maintain. This way, when/if you change the styling; then it saves having to trawl through your classes.
<?php
class Pagination
{
const DEFAULT_DISPLAYED_ROWS = 30;
const DEFAULT_GET_INDEX = 'page';
const DEFAULT_MAX_LINKS_DISPLAYED = 5;
protected $get_index;
protected $max_links_displayed;
protected $total_number_of_records;
protected $displayed_rows;
public function get_displayed_rows()
{
return $this->displayed_rows;
}
protected $start;
public function get_start()
{
return $this->start;
}
public function __construct( $total_number_of_records , $displayed_rows = null , $max_links_displayed = null , $get_index = null )
{
$this->total_number_of_records = is_int( $total_number_of_records ) && $this->total_number_of_records >= 0 ? $total_number_of_records : null;
if ( !isset( $this->total_number_of_records ) )
throw new Exception( '$total_number_of_records must be an int and greater than or equal to 0' );
// Check is $displayed_rows is set and a int, otherwise it is the default.
$this->displayed_rows = isset( $displayed_rows ) && is_int( $displayed_rows ) ? $displayed_rows : self::DEFAULT_DISPLAYED_ROWS;
// Check is $max_links_displayed is set and an int, otherwise it is the default.
$this->max_links_displayed = isset( $max_links_displayed ) && is_int( $max_links_displayed ) && $max_links_displayed >= 0
? $max_links_displayed : self::DEFAULT_MAX_LINKS_DISPLAYED;
// Check is $get_index is set and a string, otherwise it is the default.
$this->get_index = isset( $get_index ) && is_string( $get_index ) ? $get_index : self::DEFAULT_GET_INDEX;
// Check the if the page start ($_GET[$this->get_index]) is set, int, greater than 0 and less than $total_number_of_records.
$this->start = isset( $_GET[ $this->get_index ] ) && is_int( (int)$_GET[ $this->get_index ] ) && $_GET[ $this->get_index ] >= 0
&& $_GET[ $this->get_index ] < $total_number_of_records ? $_GET[ $this->get_index ] : 0;
// Round down to a mulitple of $this->displayed_rows.
$this->start = $this->start >= $this->displayed_rows ? $this->round_to_multiple( $this->displayed_rows , $this->start ) : 0;
}
public function get_paginate_links()
{
// Get a clean URL.
$url = isset( $_GET[ $this->get_index ] ) ? str_ireplace( array( '?' . $this->get_index . '=' . $_GET[ $this->get_index ] ,
'&' . $this->get_index . '=' . $_GET[ $this->get_index ] ) , '' , $_SERVER[ 'REQUEST_URI' ] ) : $_SERVER[ 'REQUEST_URI' ];
$url = htmlentities( $url . ( ( substr( $url , -4 ) == '.php' || substr( $url , -1 ) == '/' ) ? '?' : '&' ) . $this->get_index . '=' );
$links = array();
// If the current paginate is not the first.
if ( $this->start > 0 )
{
$links[] = $this->paginate_link( 'First' , $url . '0' );
$links[] = $this->paginate_link( 'Prev' , $url . ( $this->start - $this->displayed_rows ) );
}
// The last multiple to be allowed to display.
$last = $this->round_to_multiple( $this->displayed_rows , $this->total_number_of_records - 1);
// Get the page currently on.
$current_page = ( $this->start / $this->displayed_rows ) + 1;
// Get the last page number to be displayed.
$last_page = ( $last / $this->displayed_rows ) + 2;
// Get the page to start counting from.
$start_page = $current_page > 0 ? $current_page - ( floor( $this->max_links_displayed / 2 ) - ( $this->max_links_displayed % 2 == 0 ? 1 : 0 ) ) : 1;
$start_page = $start_page + $this->max_links_displayed > $last_page ? $last_page - $this->max_links_displayed : $start_page;
$links_displayed = 0;
while ( $links_displayed < $this->max_links_displayed )
{
// If the last page is reached before the maximum links have been displayed.
if ( $start_page + $links_displayed == $last_page )
break;
// If the current page (in the loop) is not in arrears (negative).
if ( $start_page + $links_displayed > 0 )
{
if ( $start_page + $links_displayed == $current_page )
$links[] = $this->paginate_link( $start_page + $links_displayed , '#', true );
else
$links[] = $this->paginate_link( $start_page + $links_displayed , $url . ( ($start_page + $links_displayed - 1) * $this->displayed_rows ) );
}
else
$this->max_links_displayed++;
$links_displayed++;
}
// If the current page is not the last.
if ( $current_page < $last_page - 1 )
{
$links[] = $this->paginate_link( 'Next' , $url . ( $this->start + $this->displayed_rows ) );
$links[] = $this->paginate_link( 'Last' , $url . $last );
}
return $links;
}
private function paginate_link( $name , $href , $current = null )
{
if ( isset( $current ) )
return array( 'name' => $name , 'href' => $href , 'current' => $current );
else
return array( 'name' => $name , 'href' => $href );
}
private function round_to_multiple( $factor , $value )
{
return $value % $factor == 0 ? $value : ( ceil( $value / $factor ) - 1 ) * $factor;
}
}
?>
To be called similarly by your method.<?php
$Pagination = new Pagination( 10 , 2 , 3 );
// ...
// mysql_query( 'SELECT * FROM table LIMIT ' . $Pagination->get_start() . ', ' . $Pagination->get_displayed_rows() );
// ...
foreach ( $Pagination->get_paginate_links() as $link )
{
echo '<a href="' . $link[ 'href' ] . '"' . ( isset( $link[ 'current' ] ) ? 'style="text-decoration: none;"' : '' ) . '>' . $link[ 'name' ] . '</a> ';
}
?>