Part of the EllisLab Network
   
 
Easy Pagination Mod for using Page Numbers instead of Offsets
Posted: 23 August 2011 11:10 AM   [ Ignore ]  
Summer Student
Total Posts:  4
Joined  08-12-2010

These are instructions on how to make minor edits to the core Pagination.php class so that you can not only use page numbers in URL instead of offsets, but it’s also adaptable so that any number of per-page limits can be used.

I’ve looked far and wide for something like this, but unfortunately I’ve only found rewritten functions that become more complex and cumbersome to use than the default pagination class. So if you like the default pagination class and simply want to use page numbers instead, this is for you. Here’s my documented approach, so you can see how simple and minimal the changes are.

Controller Class

Set up your controller to pass necessary information to both Pagination and View classes. Perform limit, page and offset mathematics in the controller so that they can be passed to other functions/classes.

// set the per-page entry limit
$iLimit 10;

// set the current page number
$iPage $this->uri->segment(3);
$iPage = ($iPage !== false) ? (int)$iPage 1;

// set the offset by calculating the limit and page number
$iOffset = (($iPage 1) * $iLimit);

// set pagination configuration
$config['base_url'base_url().'entries/page';
$config['first_url'base_url().'entries';
$config['uri_segment'3;
$config['per_page'$iLimit;

// set total results from db results
$config['total_rows'$this->db->get('entries')->num_rows();

// initialize pagination
$this->pagination->initialize($config);

// load db results using limit and offset variables
$data['query'$this->db->get('entries'$iLimit$iOffset);

// load view
$this->load->view('entries'$data); 

Pagination.php Class

Make changes to Pagination class (/system/libraries/Pagination.php) so that it uses page numbers instead of offsets.

OLD (lines 146–153):

if ($CI->uri->segment($this->uri_segment) != 0)
{
    $this
->cur_page $CI->uri->segment($this->uri_segment);

    
// Prep the current page - no funny business!
    
$this->cur_page = (int) $this->cur_page;

NEW:

Add ‘else’ option to if-statement to make sure default is; page = 1.

if ($CI->uri->segment($this->uri_segment) != 0)
{
    $this
->cur_page $CI->uri->segment($this->uri_segment);

    
// Prep the current page - no funny business!
    
$this->cur_page = (int) $this->cur_page;
}
else
{
    $this
->cur_page 1;


OLD (line 175):

$this->cur_page floor(($this->cur_page/$this->per_page) + 1); 

NEW:

Simply comment out this line so current page obeys controller/URI.

//$this->cur_page = floor(($this->cur_page/$this->per_page) + 1); 


OLD (line 206):

$i $uri_page_number $this->per_page

NEW:

Previous page should always be current page subtracted by 1.

$i $uri_page_number 1


OLD (line 230):

if ($this->cur_page == $loop

NEW:

URIs missing pagination should be considered page 1.

if ($this->cur_page == $loop || ($this->cur_page == && $this->cur_page == $loop)) 


OLD (line 238–247):

if ($n == '' && $this->first_url != '')
{
    $output 
.= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'">'.$loop.'</a>'.$this->num_tag_close;
}
else
{
    $n 
= ($n == '') ? '' $this->prefix.$n.$this->suffix;

    
$output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$n.'">'.$loop.'</a>'.$this->num_tag_close;

NEW:

Page URLs should use page numbers and not offsets.

if ($n == '' && $this->first_url != '')
{
    $output 
.= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$loop.'">'.$loop.'</a>'.$this->num_tag_close;
}
else
{
    $n 
= ($n == '') ? '' $this->prefix.$n.$this->suffix;

    
$output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$loop.'">'.$loop.'</a>'.$this->num_tag_close;


OLD (line 256):

$output .= $this->next_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.($this->cur_page $this->per_page).$this->suffix.'">'.$this->next_link.'</a>'.$this->next_tag_close

NEW:

Next page should always be the sum of current page and 1.

$output .= $this->next_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.($this->cur_page 1).$this->suffix.'">'.$this->next_link.'</a>'.$this->next_tag_close


OLD (line 262):

$i = (($num_pages $this->per_page) - $this->per_page); 

NEW:

Last page should be the total number of pages.

$i $num_pages


Conclusion

That’s all you have to do. After these changes, you will be able to use pagination as normal. It’s also easy to modify your controller for more advanced queries since all the pagination class requires is the number of results.

Profile
 
 
Posted: 23 August 2011 11:43 AM   [ Ignore ]   [ # 1 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1835
Joined  12-08-2009

These changes should be made as an extension of the pagination library, not by modifying the core version. You would still be able to load and use the pagination, and you would not lose the ability to upgrade CI.

 Signature 

@basdflasjk | BitAuth: Authentication and Role-based Permissions | Session Library Replacement


Please read the User Guide! (Upgrading from a previous version?)

Profile
 
 
Posted: 23 August 2011 05:01 PM   [ Ignore ]   [ # 2 ]  
Summer Student
Total Posts:  4
Joined  08-12-2010
danmontgomery - 23 August 2011 03:43 PM

These changes should be made as an extension of the pagination library, not by modifying the core version. You would still be able to load and use the pagination, and you would not lose the ability to upgrade CI.

I agree - and anyone can certainly duplicate the class and make these modifications. That’s up to individual developers.

But the point is to show exactly what needs modification and the steps to do so, especially for something that is a significant issue for many developers. I know that I wish I saw this post before figuring it out myself, and this post is for those people.

I don’t even know why the default class doesn’t support this (very basic) functionality.

Profile
 
 
Posted: 24 August 2011 06:56 AM   [ Ignore ]   [ # 3 ]  
Lab Assistant
RankRank
Total Posts:  159
Joined  08-15-2010

Shameless plug : http://bitbucket.org/JonoB/ci-paginator/

Profile
 
 
Posted: 26 August 2011 04:44 AM   [ Ignore ]   [ # 4 ]  
Summer Student
Total Posts:  1
Joined  08-25-2011

Thanks!  cheese

Profile
 
 
Posted: 26 August 2011 07:48 PM   [ Ignore ]   [ # 5 ]  
Summer Student
Total Posts:  6
Joined  09-07-2009

A minor problem: Your change on lines 238-247 seems to break usage of $first_url, $prefix, and $suffix.  It would be better to change those lines to the following:

OLD (238-247):

if ($n == '' && $this->first_url != '')
{
    $output 
.= $this->num_tag_open'<a '.$this->anchor_class.'href="'.$this->first_url.'">'.$loop.'</a>'.$this->num_tag_close;
}
else
{
    $n 
= ($n == '') ? '' $this->prefix.$n.$this->suffix;

    
$output .= $this->num_tag_open'<a '.$this->anchor_class.'href="'.$this->base_url.$n.'">'.$loop.'</a>'.$this->num_tag_close;

NEW:

if ($n == '' && $this->first_url != '')
{
    $output 
.= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'">'.$loop.'</a>'.$this->num_tag_close;
}
else
{
    $n 
= ($n == '') ? '' $this->prefix.$loop.$this->suffix;

    
$output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$n.'">'.$loop.'</a>'.$this->num_tag_close;
Profile