I am working on a online newspaper/blogging application with CodeIgniter 3.1.8 and Bootstrap 4.
I have separated the application’s back-end (dashboard) from its front-end and used Twig for the front-end views and adding theming.
I thought it was a good idea to add a search functionality for the back-end, for ease of navigating through one’s own posts (articles).
In my Posts controller (applicationcontrollersdashboardPosts.php
) I have:
private function get_data(){ $data = $this->Static_model->get_static_data(); $data['pages'] = $this->Pages_model->get_pages(); $data['categories'] = $this->Categories_model->get_categories(); $data['number_of_pages'] = $this->Pages_model->count_pages(); $data['number_of_posts'] = $this->Posts_model->get_num_rows(); $data['number_of_categories'] = $this->Categories_model->get_num_rows(); $data['number_of_comments'] = $this->Comments_model->get_num_rows(); return $data; } public function index() { if (!$this->session->userdata('is_logged_in')) { redirect('login'); } //load and configure pagination $this->load->library('pagination'); $config['base_url'] = base_url("/dashboard/posts"); $config['query_string_segment'] = 'page'; $config['total_rows'] = $this->Posts_model->get_num_rows(); $config['per_page'] = 10; if (!isset($_GET[$config['query_string_segment']]) || $_GET[$config['query_string_segment']] < 1) { $_GET[$config['query_string_segment']] = 1; } $limit = $config['per_page']; $offset = ($this->input->get($config['query_string_segment']) - 1) * $limit; $this->pagination->initialize($config); $data = $this->get_data(); $data['posts'] = $this->Posts_model->get_posts($limit, $offset); $data['offset'] = $offset; $this->load->view('dashboard/partials/header', $data); $this->load->view('dashboard/posts'); $this->load->view('dashboard/partials/footer'); } public function search() { if (!$this->session->userdata('is_logged_in')) { redirect('login'); } // Force validation since the form's method is GET $this->form_validation->set_data($this->input->get()); $this->form_validation->set_rules('search', 'Search term', 'required|trim|min_length[3]',array('min_length' => 'The Search term must be at least 3 characters long.')); $this->form_validation->set_error_delimiters('<p class = "error search-error">', '</p> '); // If search fails if ($this->form_validation->run() === FALSE) { return $this->index(); } else { $expression = $this->input->get('search'); if (!$this->session->userdata('is_logged_in')) { redirect('login'); } //load and configure pagination $this->load->library('pagination'); $config['base_url'] = base_url("/dashboard/posts"); $config['query_string_segment'] = 'page'; $config['total_rows'] = $this->Posts_model->get_num_rows(); $config['per_page'] = 10; if (!isset($_GET[$config['query_string_segment']]) || $_GET[$config['query_string_segment']] < 1) { $_GET[$config['query_string_segment']] = 1; } $limit = $config['per_page']; $offset = $limit * ($this->input->get($config['query_string_segment']) - 1); $this->pagination->initialize($config); $data = $this->get_data(); $data['expression'] = $expression; $data['posts'] = $this->Posts_model->search($expression, $limit, $offset); $data['offset'] = $offset; $this->load->view('dashboard/partials/header', $data); $this->load->view('dashboard/posts'); $this->load->view('dashboard/partials/footer'); } }
In the Posts_model model I have this for the list of posts posts:
public function get_posts($limit, $offset) { $this->db->select('posts.*,categories.name as post_category'); $this->db->order_by('posts.id', 'DESC'); $this->db->join('categories', 'posts.cat_id = categories.id', 'inner'); $query = $this->db->get('posts', $limit, $offset); return $query->result(); }
The the view (posts.php):
<div class="card-body bg-white p-0"> <div class="table-responsive"> <table class="table table-striped table-sm mb-0"> <thead> <tr> <th class="text-right">#</th> <th class="w-50">Title</th> <th>Publication date</th> <th class="text-right pr-2">Actions</th> </tr> </thead> <tbody> <?php foreach ($posts as $index => $post): ?> <tr data-slug="<?php echo $post->slug; ?>"> <td class="text-right"><?php $count = $index + 1; echo $count + $offset; ?></td> <td><?php echo $post->title; ?></td> <td><?php echo nice_date($post->created_at, 'D, M d, Y'); ?></td> <td class="text-right"> <div class="btn-group btn-group-sm" role="group"> <a href="<?php echo base_url('posts/post/') . $post->slug; ?>" class="btn btn-success"><i class="fa fa-eye"></i> View</a> <?php if(($this->session->userdata('is_logged_in') && $this->session->userdata('user_id') == $post->author_id) || $this->session->userdata('user_is_admin')) : ?> <a href="<?php echo base_url('dashboard/posts/edit/') . $post->slug; ?>" class="btn btn-success"><i class="fa fa-pencil-square-o"></i> Edit</a> <a href="#" data-slug="<?php echo $post->slug ?>" class="delete-post ajax-btn btn btn-success"><i class="fa fa-trash"></i> Delete</a> <?php else: ?> <a href="#" class="btn btn-success disabled"><i class="fa fa-pencil-square-o"></i> Edit</a> <a href="#" class="btn btn-success disabled"><i class="fa fa-trash"></i> Delete</a> <?php endif; ?> </div> </td> </tr> <?php endforeach ?> </tbody> </table> </div> <div class="card-footer bg-white py-1"> <?php $this->load->view("dashboard/partials/pagination");?> </div> </div>
While all the posts are paginated well, strangely, the search results are not paginated well: when for instance I do a search that returns 11 results, that should be displayed on two pages, the pagination shows all the pages instead of two.
I have not been able to figure out why.
Where is my mistake?
Advertisement
Answer
While all the posts are paginated well, strangely, the search results are not paginated well: when for instance I do a search that returns 11 results, that should be displayed on two pages, the pagination shows all the pages instead of two.
Because you use all rows count in total_rows config:
$config['total_rows'] = $this->Posts_model->get_num_rows();
In the search function you need to use the count of search result:
Number of rows from this result WITHOUT!!! $limit
, and $offset
:
public function search() { if (!$this->session->userdata('is_logged_in')) { redirect('login'); } // Force validation since the form's method is GET $this->form_validation->set_data($this->input->get()); $this->form_validation->set_rules('search', 'Search term', 'required|trim|min_length[3]',array('min_length' => 'The Search term must be at least 3 characters long.')); $this->form_validation->set_error_delimiters('<p class = "error search-error">', '</p> '); // If search fails if ($this->form_validation->run() === FALSE) { return $this->index(); } else { $expression = $this->input->get('search'); if (!$this->session->userdata('is_logged_in')) { redirect('login'); } //load and configure pagination $this->load->library('pagination'); $config['base_url'] = base_url("/dashboard/posts"); $config['query_string_segment'] = 'page'; // Only one line changed below $config['total_rows'] = $this->Posts_model->search_count($expression); $config['per_page'] = 10; if (!isset($_GET[$config['query_string_segment']]) || $_GET[$config['query_string_segment']] < 1) { $_GET[$config['query_string_segment']] = 1; } $limit = $config['per_page']; $offset = $limit * ($this->input->get($config['query_string_segment']) - 1); $this->pagination->initialize($config); $data = $this->get_data(); $data['expression'] = $expression; $data['posts'] = $this->Posts_model->search($expression, $limit, $offset); $data['offset'] = $offset; $this->load->view('dashboard/partials/header', $data); $this->load->view('dashboard/posts'); $this->load->view('dashboard/partials/footer'); } }