5

This is a very irritating issue. I have my codeigniter pagination set up and so I thought working, but looking at it closer it seems that on the last page it's pulling in previous results to fill the page in.

So say I want ten per page and have fourteen results. The first page has ten results, and so does the second. When it should be the first has ten and the second has four. It would be fine if it was just repeating one result, but it's irritating to have to scroll through six previous results. Any help would be much appreciated.

in my controller I have the pagination code

$config = array();
$config["base_url"] = base_url()."myStories/".$id;
$config["total_rows"] = $this->data_model->my_count();
$config["per_page"] = 10;
$config["uri_segment"] = 3;
$config['num_links'] = 2;
$choice = $config["total_rows"] / $config["per_page"];
//$config["num_links"] = round($choice);

$this->pagination->initialize($config);
$page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;

$this->load->view('userStory_view', array(
    'query' => $this->data_model->pullMyStories($config['per_page'], $page),
    'links' => $this->pagination->create_links(),
    'user' => $this->users_model->getUser($this->user->user_id),
)); 

and then in my model I have the count and then the actual results coming back

public function my_count() {
        //This counts all the stories that belong to that author
        $author = $this->uri->segment(2);
        $this->db->where('author', $author);
        $this->db->where(array('approved !=' => 'd'));
        $query = $this->db->get('story_tbl');
        return $query->num_rows();
       }

    public function pullMyStories($limit, $start){
        //This pulls back all the stories that belong to that author
        $this->db->limit($limit, $start);
        $this->db->order_by("date", "desc");
        $author = $this->uri->segment(2);
        $this->db->where(array('approved !=' => 'd'));
        $this->db->where('author', $author);
        $story = $this->db->get('story_tbl');
        return $story->result();    
    }

the route I have set up that does work

$route['myStories/(:any)'] = "story/viewStories/$1";

I thought initially that my count was count was wrong, but even with a count of 14, 20 results come back.

For further information I am more than positive that my baseUrl is correct. I have modified my .htaccess to get rid of the index.php and have edited my route file to make the controller disappear from the url. To try and make it easy to remember for the user.

I am also very sure that the uri segments are correct. If they were not correct then my page would not be coming up at all.

I have tried all the normal solutions and nothing has worked. That is why I am asking here and why I have placed a bounty on this question.

zazvorniki
  • 3,512
  • 21
  • 74
  • 122
  • Two questions: How many items are there in total? What is your offset limit for the last page? – bottleboot Jul 19 '13 at 07:47
  • There are 14 items in total. and the limit is the same for every page, ten. Is there an offset that is specific to the last page? – zazvorniki Jul 19 '13 at 20:05
  • Have you tried returning the variable $page to your view, then doing a var_dump of the variable to see what it shows on page 2? – whispersan Jul 21 '13 at 22:07
  • Can you provide full method in your controller with parameters. How and where default $id is set? if myStories/$id, then I suppose you have done some routing, please provide them too. thx – Ula Jul 22 '13 at 02:59
  • @zazvorniki i just thought you aren't sending $author variable in pullMyStories() function it might also bcoz of have u checked it ? . I might also be wrng if $author is global variable. – Sathya Raj Jul 22 '13 at 07:13
  • What happens if you add a slash to the base_url? So: base_url()."myStories/".$id."/". The slash is there in the documentation, and if it is required it might break the pagination links. – Luc Jul 22 '13 at 14:32
  • @whispersan I have printed the $page variable to the view and it seems to come up as normal as 10....and then var_dump what variable? The $page? – zazvorniki Jul 22 '13 at 15:51
  • @Ula I did't post that originally because that is just placed in a function and the id is a variable from the url. As well I would post my routing, but I know everything there is working scene I am getting back the second page with content...just too much content. – zazvorniki Jul 22 '13 at 15:54
  • @sathya I have checked the authors variable and that is coming back just fine. – zazvorniki Jul 22 '13 at 15:55
  • @Luc If I add an extra slash to the baseUrl then an extra slash gets added to the url and the second page shows up as a blank page. – zazvorniki Jul 22 '13 at 16:00
  • Could you post the full uri part of the domain of the second page? Is it /myStories/{id}/10? Also, could you post the relevant part of the route? I -think- it has something to do with the uri segments in combination with the route and the uri_segments config value. – Luc Jul 22 '13 at 16:13
  • The full uri for the second page is http://website.com/myStories/userid/10 and I posted the route above – zazvorniki Jul 22 '13 at 16:48

8 Answers8

2
var $base_url           = ''; // The page we are linking to
var $prefix             = ''; // A custom prefix added to the path.
var $suffix             = ''; // A custom suffix added to the path.

var $total_rows         =  0; // Total number of items (database results)
var $per_page           = 10; // Max number of items you want shown per page
var $num_links          =  2; // Number of "digit" links to show before/after the currently viewed page
var $cur_page           =  0; // The current page being viewed
var $use_page_numbers   = FALSE; // Use page number for segment instead of offset
var $first_link         = 'First';
var $next_link          = '->';
var $prev_link          = '<-';
var $last_link          = 'Last';
var $uri_segment        = 2;
var $full_tag_open      = '';
var $full_tag_close     = '';
var $first_tag_open     = '';
var $first_tag_close    = ' ';
var $last_tag_open      = ' ';
var $last_tag_close     = '';
var $first_url          = ''; // Alternative URL for the First Page.
var $cur_tag_open       = '&nbsp;<strong>';
var $cur_tag_close      = '</strong>';
var $next_tag_open      = '&nbsp;';
var $next_tag_close     = '&nbsp;';
var $prev_tag_open      = '&nbsp;';
var $prev_tag_close     = '';
var $num_tag_open       = '&nbsp;';
var $num_tag_close      = '';
var $page_query_string  = FALSE;
var $query_string_segment = 'per_page';
var $display_pages      = TRUE;
var $anchor_class       = '';
Rachael
  • 299
  • 2
  • 5
  • 12
1

Your problem is that you are passing the wrong parameters to your pullMyStories method. On the first page you will be apply the following limit to your query

LIMIT 0,10

Then on the second page

LIMIT 1,10

Then on the third

LIMIT 2,10

So you pagination is only moving forward one item at a time instead of ten. So you need to change this

'query' => $this->data_model->pullMyStories($config['per_page'], $page),

To this

'query' => $this->data_model->pullMyStories($config['per_page'], ($page * $config['per_page'])),
Pattle
  • 5,983
  • 8
  • 33
  • 56
  • When I change that line now nothing shows up on the second page. – zazvorniki Jul 19 '13 at 19:48
  • Codeigniter shows the starting index of the paginated items in the assigned URI segment, rather than the actual page number so this solution would not work unless the config item $config['use_page_numbers'] was set to TRUE – whispersan Jul 21 '13 at 22:05
0

Try if it works for you:

$config = array();
$config["base_url"]     = base_url()."myStories/";         #change in base url
$config["total_rows"]   = $this->data_model->my_count();
$config["per_page"]     = 10;
$config["uri_segment"]  = 3;
$config['num_links']    = 2;
#$choice = $config["total_rows"] / $config["per_page"];
//$config["num_links"] = round($choice);

$this->pagination->initialize($config);
#$page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;  #no need of calculation here

$this->load->view('userStory_view', array(
    'query' => $this->data_model->pullMyStories($this->uri->segment(3)),   #change here send the offset directly
    'links' => $this->pagination->create_links(),
    'user' => $this->users_model->getUser($this->user->user_id),
)); 

function pullMyStories($offset = 0){
    $story = $this->db->where('author', $this->uri->segment(2))->where('approved != d')->order_by("date", "desc")->get('story_tbl', 10, $offset);
    return $story->result();
}
Nil'z
  • 7,487
  • 1
  • 18
  • 28
  • commenting out the first part resulted in the same, getting back duplicate results to fill in the second page. When I modified the query it returned a 500 error. – zazvorniki Jul 16 '13 at 20:06
  • Do `echo $this->db->last_query();die;` on the second page and see if it is returning the correct `limit` in the query. And please post your returned query here.@zazvorniki – Nil'z Jul 17 '13 at 06:04
  • I have already done that. It is returning the correct number, but it is still filling in to reach the ten per page which is why this is so irritating. – zazvorniki Jul 17 '13 at 15:48
  • Changed the above reply so check once again and let me know. – Nil'z Jul 19 '13 at 15:18
  • Now no results are coming back and if I change the code in my model it still returns a 500 error – zazvorniki Jul 19 '13 at 19:51
  • I believe that the model is returning a 500 error because it has to have the $limit and $start variables. – zazvorniki Jul 19 '13 at 20:20
  • can you put your query which is being executed in the second page? write `echo $this->db->last_query();die;` just before this line `return $story->result();` – Nil'z Jul 22 '13 at 06:21
0

I recently tried so hard to about ci pagination.

I think, your codes right.

What exactly uri string on second page?.. And this listing function is index() ?

Bora
  • 10,529
  • 5
  • 43
  • 73
  • The uri string is right, the page loads just fine....just with too many results. No I have the function only loading when a certain page is called, the user's story page so it is within a function. It's just a very large function and I didn't want to waste space. :) – zazvorniki Jul 19 '13 at 19:54
0

Try this. You just need to change the base_url in the correct way. Also be careful and check if you are getting a right number for uri_segment. If not, you can change the number, and get the correct.

    // $config = array();
    // MUST CHNGE IT I just tell the with simple example. If you have index.php, c name and method name.
    $config["base_url"] = base_url()."index.php/controller_name/function_name/"; 
    $config["total_rows"] = $this->data_model->my_count();
    $config["per_page"] = 10;
    $config["uri_segment"] = 3; // BE CARFULL with uri_segment. You need to print it, and be shre that you are getting the right number
    $config['num_links'] = 2;


    $this->pagination->initialize($config);
    $page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;

    $this->load->view('userStory_view', array(
        'query' => $this->data_model->pullMyStories($config['per_page'], $page),
        'links' => $this->pagination->create_links(),
        'user' => $this->users_model->getUser($this->user->user_id),
    ));

I update my code, I comment and $config = array(); I did it today in my computer this, and it works. I know that you maybe checked it hundred times, but Check in details it again.

UPDATE with my example:

function index() {

        $data['page_title'] = "Items";

        $config['base_url']         = base_url() .'index.php/items/index/';
        $config['total_rows']       = $this->items_model->count_items(); // Count items from DB
        $config['per_page']         = 10; 
        $config['uri_segment']      = 3;
        // Customize 
        $config['next_link']        = FALSE;
        $config['prev_link']        = FALSE;
        $config['first_link']       = 'first';
        $config['last_link']        = 'last';
        $config['cur_tag_open']     = '<a class="current">';
        $config['cur_tag_close']    = '</a>';

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

        $page                       = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;
        $data['items']              = $this->items_model->get_items($config["per_page"], $page);


        $this->load->view('invoice-items', $data);

    }
Erman Belegu
  • 4,074
  • 25
  • 39
  • I am positive I have the right base url. I have .htaccess to get rid of the index php and have changed my routes around to make it easier for the user to remember the address. And I am getting back the right url segment as well. I have checked and double checked that. – zazvorniki Jul 19 '13 at 19:46
  • I did one simple update. I did it like this today, and at my computer works. I had a same problem, but I fix it with uri segment. I use modules, and did it like $this->uri->segment(4), but you don't need to do it, because you don't have more than 3 segment, as I see. I hope that it will help you – Erman Belegu Jul 19 '13 at 23:05
  • I am very confused in what you want me to do... You want me to comment out the config array and change to uri segment to 4? Commenting out the array I'm afraid does not change a thing and I can't use the segment 4 because in the url there are only two segments before to pagination. The full url is www.website.com/myStories/userName – zazvorniki Jul 20 '13 at 00:20
  • With these that you said, I didn't see where did you make any error? I try it today, and everything is OK. I check your code again, and your code and mine was good, but I don't know where can be your problem. – Erman Belegu Jul 20 '13 at 00:28
  • I am very confused where my error is too! :) I wish I wasn't getting back too many results, makes life difficult! haha – zazvorniki Jul 20 '13 at 00:31
  • @zazvorniki I update my answer, and write my example controller. It 100% works good. Maybe it will helps you. If you need, I can show you model function too – Erman Belegu Jul 20 '13 at 00:38
0

In your controller:

$page = $this->uri->segment(3,0);

Then:

public function pullMyStories($limit, $start){

$author = $this->uri->segment(2);

$this->db
  ->select('*')
  ->where('approved !=', 'd')
  ->where('author', $author)
  ->order_by('date', 'DESC')
  ->limit($limit, $start);

$story = $this->db->get('story_tbl');

return $story->result(); 

Also where do you load the library using the line below?

$this->load->library('pagination');   
whispersan
  • 1,029
  • 2
  • 13
  • 28
  • I'm loading the pagination library in the autoload library so I don't have to restate it every time I use pagination. When I used that query statement it returned a 500 error. Just curious, but why would I want to use a query statement like that over what codeigniter recommends? – zazvorniki Jul 22 '13 at 16:11
  • Because limit should be applied after order_by http://stackoverflow.com/questions/4974639/is-mysql-limit-applied-before-or-after-order-by or http://stackoverflow.com/questions/4708708/mysql-order-by-limit Also it makes your query neater - you don't have to put $this->db on every line, and the second parameter of $this->uri->segment gives the default option if the segment does not exist, so that is tidied up a bit in your controller. Your 'date' column is it of the 'datetime' type? Have you got 16 different datetimes or are some the same? – whispersan Jul 23 '13 at 00:55
  • I should point out $this->uri->segment(2); only has one parameter. :) and my date goes into the database as a time() function and goes down to the very second. I have solved my problem though as you can see above. Someone posted the content of their pagination class and mine seemed to somehow become corrupt so that worked. – zazvorniki Jul 23 '13 at 02:43
  • The second parameter is optional, you will always have an author in the second parameter on the page where your pagination exists but unless you are on page > 1 you will not always have a third parameter, so its just a neater way of writing $page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0; Glad you solved anyway!!! – whispersan Jul 23 '13 at 02:52
0

I'm just gonna throw this in and hope it helps in some way, because I've tested and it works for me. I've made the following assumptions for testing:

  • id (as in "myStories/".$id in the controller) is taken from $this->uri->segment(2)
  • story_tbl fields I created were id, author, date

My test files were as follows:

Controller MyStories.php:

    public function index()
    {
            //loading library, model, and assumptions
        $this->load->library('pagination');
        $this->load->model('m_page', 'data_model');
        $id = $this->uri->segment(2);
        //
        //
        //Your code from here...
        //
        //
        $config = array();
        $config["base_url"] = $this->config->site_url("myStories/".$id);
        $config["total_rows"] = $this->data_model->my_count();
        $config["per_page"] = 3;
        $config["uri_segment"] = 3;
        $config["num_links"] = round($config["total_rows"] / $config["per_page"]);

        $this->pagination->initialize($config);
        $page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;

        $data = array();
        $data['query'] = $this->data_model->pullMyStories($config['per_page'], $page);
        $data['links'] = $this->pagination->create_links();
        $data['config'] = $config;
        //$data['user'] = $this->users_model->getUser($this->user->user_id);
        $this->load->view('userStory_view', $data);     
    }

BTW, you really want to be using the site_url and not base_url when defining the pagination base_url.

I also commented out the 'user' data in the controller simply because you never gave any info on that.

My test view, userStory_view.php:

<?php echo $links;?>
<!-- -->
<hr>
total rows: <?php echo $config['total_rows'];?>
<hr>
<?php echo $this->db->last_query();?>
<hr>
<!-- -->
<?php foreach ($query as $row):?>
<?php echo $row->author.'<hr>';?>
<?php endforeach;?>

I made no changes to your Model, so no need to show that here.

I added the following line to routes.php:

$route['myStories/(:any)'] = "myStories";

As I said, everything worked for me. Besides my formatting, the only changes I really made were the use of site_url() instead of base_url(), and the commenting of the user data. So pretty stuck as to why you're having issues I'm afraid.

thefunker
  • 46
  • 2
0

As far as it seems your overall pagination functionality seems to correct. what i want check would the sql query returned in each function and parameters passed to those function coz $author variable has to global and try

$this->db->last_query();

on your both functions my_count() and pullMyStories($limit, $start) and check those function returning right results.

U might also can try writing direct sql query with changing parameters like.

$sql = "SELECT * FROM some_table WHERE author = ? LIMIT ?, ?";

$this->db->query($sql, array($author, $start, $limit)); 

As i am seeing this would be mostly of query might have been wrong . Hope this helps.

Sathya Raj
  • 1,079
  • 2
  • 12
  • 30
  • I have done multiple last_query() statements and all the queries seem to come back fine, I have even run them in my database directly to see if that was somehow the issue, but they all come back how they are suppose to. – zazvorniki Jul 22 '13 at 16:02