6

My controller function

function test($start_from = 0)
{
    $this->load->library('pagination');

    $data = array();

    $per_page = 3;
    $total = $this->activity_model->count_by();

    $config['base_url'] = base_url() . 'test';
    $config['total_rows'] = $total;
    $config['per_page'] = $per_page;
    $config['uri_segment'] = 2;
    $config['num_links'] = 2;
    $config['use_page_numbers'] = TRUE;

    $data['follow'] = $this->activity_model->get($per_page, $start_from);

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

   $data['pagination'] = $this->pagination->create_links();

    $this->load->view('front_end/test' ,$data);
}

my route :

 $route['test'] = "user_activity/test";
 $route['test/(:any)'] = "user_activity/test/$1";

model :

 function get($limit,$start_from)
 {
 $sql = "SELECT * FROM user_follow LIMIT $start_from, $limit";

  $query = $this->db->query($sql);
  return $query->result_array();
 }

Problem is that I have pagination 1,2,3,4,5.... and in every page I display 3 items. I want to do that in url it show my page numbers 1,2,3,4,5

When I click second page url show 3 When I click third page url show 6 and so on +3

is it possible, I spend hours for looking advice on internet but nothing as I understand [code]$config['use_page_numbers'] = TRUE;[/code] do what I need but in my case it still do not work.

Maybe you can advice any library ?

Viktors
  • 935
  • 3
  • 13
  • 33

3 Answers3

11

I managed to do this without modifying the class. The best way will be to make a copy of the pagination class, make your changes and use it. This way if you update CI, you won't lose the modification. Here is my solution without modifying the class.

First I want to say that using only the config option $config['use_page_numbers'] = TRUE will also do the trick but not entirely. The things I found out not working using only this option are the following:
if you try to edit the url bar pages manually it treats them like offset not like pages and also if you try to go back from page 2 to page 1 using the "prev" link it also treats the page number like an an offset.

The code:

$config['base_url'] = base_url('my/url/page');
$config['total_rows'] = count($this->my_model->get_all());
$config['per_page'] = 2;
$config['use_page_numbers'] = TRUE;     
$config['uri_segment'] = 4; 

//i'm looading the pagination in the constuctor so just init here
$this->pagination->initialize($config); 

if($this->uri->segment(4) > 0)
    $offset = ($this->uri->segment(4) + 0)*$config['per_page'] - $config['per_page'];
else
    $offset = $this->uri->segment(4);
//you should modify the method in the model to accept limit and offset or make another function - your choice       
$data['my_data'] = $this->my_model->get_all($config['per_page'], $offset);

This way
page = false (my/url) or (my/url/page) - basically if the 4th uri segment is false,
page = 0 (my/url/page/0),
and
page = 1 (my/url/page/1)

will all display the first page and then the other links will be working fine. I'm also validating the page e.g - if someone wants to enter (my/url/page/2323) this will throw an error and in the model you should check if the result is false and if it is the controller should show an error page or something. Hope this helps.

Nosebleed
  • 233
  • 2
  • 8
8

Make the following changes in 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 == 1 && $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; 

Replace all the old lines with new lines. Make sure you do a backup of file before changing.

Hope this helps :)

EDIT:

You need to update your controller function test like :

function test($start_from = 0)
{
    $this->load->library('pagination');

    $data = array();

    $per_page = 3;
    $total = $this->activity_model->count_by();

    $config['base_url'] = base_url() . 'test';
    $config['total_rows'] = $total;
    $config['per_page'] = $per_page;
    $config['uri_segment'] = 2;
    $config['num_links'] = 2;
    $config['use_page_numbers'] = TRUE;

    $start = $per_page * ($start_from-1);

    $data['follow'] = $this->activity_model->get($per_page, $start);

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

    $data['pagination'] = $this->pagination->create_links();

    $this->load->view('front_end/test' ,$data);
}

Here i have added a new variable $start which is $per_page * ($start_from-1). Now pass this $start as argument to model.

What this do is multiply the number of items per page with (current page number -1 ) .This means if your items per page is 10 and you are on the second page the $start = 10 *(2-1) which gives 10. So your result will start from 10,20 and so one

Hope this helps :)

Sabari
  • 6,205
  • 1
  • 27
  • 36
  • There will be some small changes in the line numbers. Any way give it a try. Mine is a little old version. Please let me know if it works :) – Sabari Jan 29 '12 at 03:07
  • Pagination links coming perfectly, Even in URL parameter is coming proper.. But now display result is changed. I have member gallery. When I click on “2nd page link” then same member again repeating in next page. So I have to do any settings for that? because in earlier query it was like this.. LIMIT 0,10 LIMIT 10,10 And Now it is coming like this LIMIT 0,10 LIMIT 2,10 LIMIT 3,10 – Viktors Jan 29 '12 at 17:49
  • You need to change your code likewise. Codeingter default pagination is offset. SO the offset value is passed to take the starting point of the result. We have changed that now... We need to change the code likewise.. I pasted only the pagination code here – Sabari Jan 29 '12 at 17:53
  • IN your code the $start_from you are passing is the function argument which we will get from the pagination which is 1,2 ,3 etc. I will show it in my edit – Sabari Jan 29 '12 at 17:54
  • $start_from = $start_from > 1 ? $start_from - 1 : 0 ; $start_from = $start_from * $per_page; – Viktors Jan 29 '12 at 17:57
  • and it start working ... just interesting is the code after upgrading must work with numbers so good like without numbers. If I use additional code for it so it is ok ? – Viktors Jan 29 '12 at 17:58
  • thank you as I see on firs look it is the same as I write below only you have it in one line – Viktors Jan 29 '12 at 18:05
0

You can avoid php errors if someone manually entering the page number from the URL:

for example my/url/page/786 your result might not have anything to display for the query 786 , by default it will show you php error..to avoid this you can use:

if (isset($result)) {
  $isArray = is_array($result) ? "YES" : "NO"; //check that result is an array or not as per your requirement.
  if ($isArray == "YES") {
   echo "show your stuffs here..";
  }
  else{
   echo "display your message instead for php error here..";
  }
}

hope this helps... for query tweet me at twitter @sufiyantech

Mohammed Sufian
  • 1,743
  • 6
  • 35
  • 62