Cakephp search with pagination
In Cakephp we show this listing using function index(), of the controller. The index.ctp will show all the listings.
For example: The list of posts is displayed as in the below image.
Adding search text box in index.ctp
Now in this index page, I want to add search text box through which I can search any item on the index page.
So let’s edit the index.ctp file of the posts. Go to folder View->Posts->index.ctp and open it to edit. Here I have created a small form which is having a text box to search an item in index.ctp, for cakephp search functionality.
Add below code in index.ctp, above the table.
<?php echo $this->Form->create('Post',array('action'=>'search')); echo $this->Form->submit('Search'); echo $this->Form->end(); ?>
This will create a small cakephp search text box above the table of posts listing. Like below image.
In the above form, I have given an ‘action’ as ‘search’. So that when the search button gets clicked this form will redirect to ‘search’ function. But as we don’t have ‘search’ function yet in PostsController, go to PostsController and create ‘search’ function like below.
public function search() { $this->render('/Posts/index'); }
In this function I have used “$this->render(‘/Posts/index’);”. This code will render the same “index.ctp” file when the ‘search‘ function gets called. So that we don’t have to create separate ‘search.ctp’ file for ‘search’ action. We don’t even require a ‘search.ctp’ file as this file would duplicate table code same as ‘index.ctp’ and will show the same result of posts listings. Hence I have directly rendered ‘index.ctp’ through ‘search’ action.
Here we have done with half part of search functionality. Let’s proceed to next half of cakephp search functionality with pagination.
Making conditions array for paginator component for cakephp search
Now let’s say I want to select few posts which are having “First Post” as a post title, then I can write a simple select SQL query as
select * from posts where title = ‘First Post’;
Here I already know that I want to search a post with the title ‘First Post‘ hence I have used equals to “=” sign in select query. But if I am not sure what is the complete title and I know only some text present in the title, let’s say I know a text ‘First‘ in the title then also I can search posts listing using below SQL query.
select * from posts where title like ‘%First%’;
Here I have used a keyword “like” in query surrounded with “%” symbols. “%” indicates that there would be some text present before and after ‘First’. So using this query we can get all the posts list which are having ‘First’ in their title.
Now to implement this thing in Cakephp’s “search” action we will use “Paginator” component. Lets add a below code in “search” function in “PostsController“.
public function search() { if ($this->request->is('post')) { if(!empty($this->request->data) && isset($this->request->data) ) { $search_key = trim($this->request->data['Post']['search_key']); $conditions[] = array( "OR" => array( "Post.title LIKE" => "%".$search_key."%", "Post.body LIKE" => "%".$search_key."%" ) ); } } $this->Paginator->settings = array('all', 'conditions' => $conditions, 'limit' => 4 ); $this->set('posts', $this->Paginator->paginate()); $this->render('/Posts/index'); }
In the above code, I have simply checked the data posted from search text box from index.ctp. And collected search_key in the $search_key variable.
Next, we need to build a $conditions array to send our search key to paginator component. This conditions array would have same sql query type “LIKE” keyword. I have used “OR” in conditions to make two conditions check. Next, this $conditions array is passed to Paginator settings and call pagiate() method.
Let’s see the result.
Resolving notice and storing search conditions in a session variable
As we see in above image, we got the result where “First” is present in the title. Now enter “post” in a search box and verify the result. Also, try to move on next page using pagination links. Furthermore, you may see a result like below.
As a result, here a notice saying “Undefined variable: conditions” is visible. This is because as we click on pagination links or “Next” button, the page gets refreshed and a new request gets sent. Because of which search_key is not again sent to the ‘search‘ function as the search form is not submitted. Hence Paginator would not have its $conditions set.
To overcome this difficulty we have to keep our $conditions array in session and every time needs to check and assign it to Paginator, on every new page request. So let us add that code in “search” function.
public function search() { if ($this->request->is('post')) { if(!empty($this->request->data) && isset($this->request->data) ) { $search_key = trim($this->request->data['Post']['search_key']); $conditions[] = array( "OR" => array( "Post.title LIKE" => "%".$search_key."%", "Post.body LIKE" => "%".$search_key."%" ) ); $this->Session->write('searchCond', $conditions); $this->Session->write('search_key', $search_key); } } if ($this->Session->check('searchCond')) { $conditions = $this->Session->read('searchCond'); } else { $conditions = null; } $this->Paginator->settings = array('all', 'conditions' => $conditions, 'limit' => 4 ); $this->set('posts', $this->Paginator->paginate()); $this->render('/Posts/index'); }
As you see I have used session write a method to store $conditions variable in “searchCond” session variable. Furthermore, I have also stored $search_key in “search_key” session variable. This $search_key will be used in the index.ctp file, to persist the search key in search text box.
Also in if statement check the session variable “searchCond” using “$this->Session->check(‘searchCond’)”, at every new request and assign to $conditions variable, if not set then assign blank to $conditions. This code will check at every new request whether the previous search key is available or not.
That’s it. We are done with “search” action. This will make your search functionality with pagination work fine.
Finalizing the cakephp search functionality
Now, in addition, add below code to the index.ctp file, above the search form.
if($this->Session->read('search_key') != "") { $search_key = $this->Session->read('search_key'); } else { $search_key = ""; }
Now every time when you click on “Next” button or pagination links, the search key persists and pagination will also work for search conditions.
Also if you want to return back to normal index page or you want to clear your search, then we need a simple reset link, which will clear the $conditions array and search key.
Finally lets add a reset link in our search form and create a “reset” function in “PostsController“.
<?php echo $this->Form->create('Post',array('action'=>'search')); echo $this->Form->input('search_key', array('value' => $search_key)); echo $this->Form->submit('Search'); echo $this->Html->link('Reset', array('action'=>'reset')); echo $this->Form->end(); ?>
index.ctp
public function reset() { $this->Session->delete('searchCond'); $this->Session->delete('search_key'); $this->redirect(array('action' => 'index')); }
PostsController.php
In conclusion, this is the simple implementation of search functionality. You can implement cakephp search functionality with your requirements and needs. Hope this post will help you in your project.
More important Cakephp related tutorials are as follows:
- CakePHP 3 Login functionality-Authentication and Authorization-Part 1
- Cakephp 3 Login functionality-CakePHP 3 authorization-Part 2
- Pagination in PHP
Subscribe here by email for more tutorials:
How would I delete the session when I exit the search view?
Hello igor,
Generally, this problem occurs when your path /cake/app/tmp/cache and other subdirectories are not writable, on the server.
You need to give write access permission to your folders and subfolders for a cache. For live environment on the server just try to set permissions code on above path to 777.
Also, try by adding below code in your bootstrap.php file
Cache::config(
'default', array(
'engine' => 'File',
'duration' => '+1 hours',
)
);
Hope this will solve your problem 🙂
Hi,
thank you for this. But i have problem with session.. :/ Do you know why show me this message?
Error: Call to a member function write() on null …
error shows on this line of code:
$this->Session->write('searchCond', $conditions);
$this->Session->write('search_key', $search_key);
and this:
if ($this->Session->check('searchCond')) {
$conditions = $this->Session->read('searchCond');
} else {
$conditions = null;
}
i use CakePHP 2.9.3… sory for my english… 😉
a $this->Form->control(…..) is missing in your index-View 😉