Andy Hawthorne
I write and I code.
How to paginate search results with CodeIgniter 2.1
This article shows you how to paginate search results with CodeIgniter. The paginate library available in the CodeIgniter framework is very useful. It is also straightforward to implement. However, offering your users the ability to click through pages after a search needs a little more work.
Getting Started
This article is a follow up to my previous article using the built in library to paginate query results from a database. You should read that one first, if you haven’t already. If you are new to CodeIgniter, then this article will help you get started with the framework.
The Problem
So what we want to do is as follows: we have provided our users with a search form, so that they can search the world database we created in the previous article.
The results of that search, might be small in number, but it might also produce a lot of records. Presenting the result set in a paginated list would therefore create a more Google-like experience for our users.
The problem is: because of the stateless nature of HTTP, when the user clicks through the pagination links, the system will break because we will lose the search term that the user entered in the search box.
There is a solution though, so lets write some code.
Counting the records based on the user search term
We’ll start with the model. What we need is a way to count the number of records found for the users search. In the basic pagination example, getting a record count was easy. We used CodeIgnIters ActiveRecord library count_all method to return the number of records in the database table.
That won’t do for our search results though. We need to count only the number of records the search query produces. That means we need a method parameter containing the search term from the form that the user submitted. Then we can use COUNT(*) to get the number of results.
Here is the method then, that needs to be added to the search_model.php file. that will achieve what we need:
public function search_record_count($searchterm)
{
$sql = "SELECT COUNT(*) As cnt FROM Country
WHERE Continent LIKE '%" . $searchterm . "%'";
$q = $this->db->query($sql);
$row = $q->row();
return $row->cnt;
}
Here, you can see that we are passing in the search term the user entered (we’ll look at how we got that in a moment), and then we are using COUNT(*) to perform a query on the database table ‘Country’.
New Controller Method and the Search Term
In our controller welcome.php, we need to add a new method we’ll call search. In the method, we’ll grab the form value $_POST’ed from the search form:
public function search
{
$searchterm = $this->input->post('searchterm',TRUE);
We are using CodeIgniters input class here, and it’s XSS filter, to make sure there is nothing nasty being entered into the search form.
Don’t forget to call the paginate library; either in the constructor method of welcome.php, or the search method:
$this->load->library('pagination');
The Paginate Library Config Options
Now we can add the configuration parameters to the method. These are very similar to the options set in the example1 method from the basic pagination article:
$config['base_url'] = base_url() . 'welcome/search'; $config['total_rows'] = $this->search_model->search_record_count($searchterm); $config['per_page'] = 20; $config['uri_segment'] = 3; $choice = $config['total_rows']/$config['per_page']; $config['num_links'] = round($choice); $this->pagination->initialize($config);
You can see that we are now calling our new search_record_count method, and we are passing the search term from the form to it. The $config['base_url'] property has changed too, to reflect the fact that we want to paginate through the search results.
To limit the query to the number of records per page, and the page number, we will need to send in a limit value to the method in the search_model that does the actual searching.
When the pagination links are being clicked, they will set a page number in the 3rd segment of the url. We can check for that value to send to our search query. In the search method in the welcome controller add this:
$limit = ($this->uri->segment(3) > 0)?$this->uri->segment(3):0;
Here, we are using the PHP ternary operator to assess whether the uri segment is set. If it is, we’ll set the $limit variable to its value, otherwise, we set the variable to 0.
The next thing we need to add to the search method, is a call to the search method in the search_model that will return the result set. We’ll create the method in the search_model in a moment, but first, let’s update the controller method:
$data['results'] = $this->search_model->search($searchterm,$limit);
$data['links'] = $this->pagination->create_links();
$data['searchterm'] = $searchterm;
$this->load->view('search',$data);
We have created an array called $data that will hold the search results, pagination links and the search term for use in the view we’ll create called ‘search’.
The search method in the model
So the search method needs to carry out the search on the Country table based on the passed in search term. We also pass in the $limit value to establish where in the result set we should start from. You can read about the MySQL limit clause here.
Here is what it looks like:
public function search($searchterm,$limit)
{
$sql = "SELECT * FROM Country
WHERE Continent LIKE '%" . $searchterm . "%' LIMIT " .$limit . ",20";
$q = $this->db->query($sql);
if($q->num_rows() > 0)
{
foreach($q->result() as $row)
{
$data[] = $row;
}
return $data;
}
else
{
return 0;
}
}
This should be fairly self explanatory. Notice that we have set the number of results per page manually. That could also be a passed in parameter if we so wished.
The Search View
We now need to create a new view called search.php. It can be pretty much identical to the other called example1.php. But we just need a search form to be included:
Add the search form to the example1.php view too, so that you try a search from there. The form action should point to the search method in the welcome controller.
Try a search on a continent: (that is the way this example is set up. You could of course, change things to search on different values in the database)
You’ll see a set of results come back, and the will be a nice set of pagination links. The problem will come when you click on the pagination links. You’ll notice that the query is no longer working. The displayed results will include everything in the table.
So what has gone wrong? The problem is, that http is a stateless protocol. That means it can’t keep hold of data between pages. As you click the links, the pages re-submit, and the search value is lost. We can fix that though.
Retaining the search value so that the Results Paginate
The solution is simple. We’ll employ CodeIgniters session library to keep hold of the search term until we are ready to destroy it.
One way to go about fixing the problem, is to write a handler method in our search_model. The purpose of the method, will be to check the various different states the $searchterm variable could be in. Lets have a look at the code:
public function searchterm_handler($searchterm)
{
if($searchterm)
{
$this->session->set_userdata('searchterm', $searchterm);
return $searchterm;
}
elseif($this->session->userdata('searchterm'))
{
$searchterm = $this->session->userdata('searchterm');
return $searchterm;
}
else
{
$searchterm ="";
return $searchterm;
}
}
All we are doing here is: checking that the $searchterm variable is set (because the user submitted the search form), and assigning it to a session, returning the session variable if it is already set, or returning an empty string if nothing is set.
Now we can call this method in the search method of the welcome controller:
$searchterm = $this->search_model->searchterm_handler($this->input->get_post('searchterm', TRUE));
so that what ever state the $searchterm variable is in, it is now being tracked through our application. What that means, is the value the user originally typed will be held in the session variable. That will persist across pagination link clicks, therefore ensuring that our pagination now works correctly.
This assumes that you are autoloading the session library. If not, you’ll need to call it in the search method too.
Wrapping Up
There is one other thing we can do. Add the following code to the beginning of the example1 method in the welcome controller:
$this->session->unset_userdata('searchterm');
This will make sure that the session variable gets reset when users start a new search.
So in this article you have seen how you can paginate database search results with CodeIgniter. You have seen how to ensure that the search value persists across page clicks, and how to calculate the number of records returned on the fly.
A fully working example is available on Github.
Feel free to share your thoughts by commenting below. If you enjoyed this article, please consider subscribing.
Tags: Codeigniter, pagination, search results


