Click here to Skip to main content
Click here to Skip to main content
Alternative Tip/Trick

Tagged as

Dynamic Pagination

, 25 Jan 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
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> ';
}
 
?>

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

fly904
Software Developer
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
GeneralMy vote of 1 Pinmemberjnrx7-Oct-12 19:03 
GeneralReason for my vote of 5 Returning value is better than direc... PinmemberRes_Nullius12-Aug-11 1:54 
GeneralReason for my vote of 5 ?a marche vraiment bien... Pinmembertsoye19-Jul-10 8:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 25 Jan 2010
Article Copyright 2010 by fly904
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid