4
votes

I'm using codeigniter and the pagination class. This is such a basic question, but I need to make sure I'm not missing something. In order to get the config items necessary to paginate results getting them from a MySQL database it's basically necessary to run the query twice is that right?

In other words, you have to run the query to determine the total number of records before you can paginate. So I'm doing it like:

Do this query to get number of results

$this->db->where('something', $something);
$query = $this->db->get('the_table_name');
$num_rows = $query->num_rows();

Then I'll have to do it again to get the results with the limit and offset. Something like:

$this->db->where('something', $something);
$this->db->limit($limit, $offset);
$query = $this->db->get('the_table_name');
if($query->num_rows()){

    foreach($query->result_array() as $row){

         ## get the results here
    }
}

I just wonder if I'm actually doing this right in that the query always needs to be run twice? The queries I'm using are much more complex than what is shown above.

3

3 Answers

1
votes

Unfortunately, in order to paginate you must know how many elements you are breaking up into pages.

You could always cache the result for the total number of elements if it is too computationally expensive.

1
votes

Yeah, you have to run two queries, but $this->db->count_all('table_name'); is one & line much cleaner.

0
votes

Pagination requires reading a record set twice:

  1. Once to read the whole set so that it can count the total number records
  2. Then to read a window of records to display

Here's an example I used for a project. The 'banner' table has a list of banners, which I want to show on a paginated screen:

  • Using a public class property to store the total records (public $total_records)
  • Using a private function to build the query (that is common for both activities). The parameter ($isCount) we pass to this function reduces the amount of data the query generate, because for the row count we only need one field but when we read the data window we need all required fields.
  • The get_list() function first calls the database to find the total and stores it in $total_records and then reads a data window to return to the caller.
  • Remember we cannot access $total_records without first calling the get_list() method !

class Banner_model extends CI_Model {

public $total_records; //holds total records for get_list()

public function get_list($count = 10, $start = 0) {
    $this->build_query();
    $query = $this->db->get();
    $result = $query->result();
    $this->total_records = count($result); //store the count

    $this->build_query();
    $this->db->limit($count, $start);
    $query = $this->db->get();
    $result = $query->result();

    return $result;
}

private function build_query($isCount = FALSE) {
    $this->db->select('*, b.id as banner_id, b.status as banner_status');
    if ($isCount) {
        $this->db->select('b.id');
    }
    $this->db->from('banner b');
    $this->db->join('company c', 'c.id = b.company_id');
    $this->db->order_by("b.id", "desc"); //latest ones first
}

And now from the controller we call:

$data['banner_list'] = $this->banner_model->get_list();
$config['total_rows'] = $this->banner_model->total_records;

Things get complicated when you start using JOINs, like in my example where you want to show banners from a particular company! You may read my blog post on this issue further:

http://www.azmeer.info/pagination-hitting-the-database-twise/