Hi CakePHP bakers,
Have you ever came across with a situation where searched filtering goes off (breaks) when you paginated through pages in your web app which was built using CakePHP 1.3 ? Actually, recently, I got an opportunity to deal with a similar problem and it took me a considerable time to judge the root cause behind this problem. I believe, at least there are few people out there who are struggling to get rid from this same situation. So this post is for you people, bakers 🙂
Exact problem :- Assume you have a page, which you are supposed to do a search (Searching users in the db, who have the last name of ‘Silva’). After you perform the search, you will be taken to a page where you will see the filtered results (In this case people who have ‘Silva’ as their last name). (Normally results will be showing below the search criterias, so you will be redirected to the same page with filtered results). According the SQL limit you have set in your controller, the results will be grouped and showed like in the image below. The problem is when you browse through page 2,3,4 and so on from the pagination links, all your search criterias will go off and results will appear as there was no filter has defined. So in other words you will never be able to access the filtered results except first page. I hope the problem is crystal clear. (Please keep in mind that there is Ajax filtering and pagination available in CakePHP and I am not focussing on that direction)
Now, let’s see why this happens and discuss some possible solutions.
Most of the time we forget that there are two types of data receiving methods we have to consider when it comes to passing data from a view to its controller. In a Controller, we all know that we can access data (fields) which have been passed from the view by calling ‘$this->data[‘ModelName’][‘FieldName’]‘. But we forget that there is something called URL parameters. In CakePHP search criterias and values are passed in the URL. So in Controller, you have to access them by calling ‘$this->passedArgs[‘ModelName.FieldName‘]‘. So in other words in your controller, for one search criteria, you will need to have two IF statements to check these two passing values. See below, (you will see three IF statements, because I normally check whether parameters/data have been actually set before stepping in, because this will increase performance and prevent from unnecessary logging to the log/debug file)
$condition_ary = array();
if(isset($this->data[‘ModelName‘][‘FieldName‘]) || isset($this->passedArgs[‘ModelName.FieldName‘]))
//IF statement 1
$condition_ary = ‘ModelName.FieldNameLIKE \’%’.trim($this->data[‘ModelName‘][‘FieldName‘]).’%\”;
$this->passedArgs[‘ModelName.FieldName‘] = trim($this->data[‘ModelName‘][‘FieldName‘]);
//IF statement 2
$condition_ary = ‘ModelName.FieldName LIKE \’%’.$this->passedArgs[‘ModelName.FieldName‘].’%\”;
Normally, when you perform an initial search, in your Controller, the code will step in to the “IF Statement 1” in above code. Because the criterias you provide in your view will be passed as POST to the controller and ‘$this->data[‘ModelName‘][‘FieldName‘]‘ is capable of handling it. But when you paginate it, the typed/selected (text box/ drop down) values will be passed from the URL. See below,
So you can see from the URL that someone requests the second page from the filtered results who have the last name as ‘silva’. To deal with this kind of a request, back in the controller, you definitely need this line (IF statement 2) ‘$this->passedArgs[‘ModelName.FieldName‘]‘. This is where most of us forget to mention. Without this line your function is incapable of handling such request.
Also, just considering is not enough, from the first search you have to pass this to the View. Check this line in above code (IF statement 1) “ $this->passedArgs[‘ModelName.FieldName‘] = trim($this->data[‘ModelName‘][‘FieldName‘]); “. So basically what it does is pass the searched value to the View using passedArgs CakePHP function.
There is one more thing you have to consider to make this work. Make sure you have inserted following line in your View file, to tell the View that you should be capable of receiving URL passed parameters.
<?php $paginator->options(array(‘url’ => $this->passedArgs)); ?>
No matter how good you are inside the Controller, but without above line in the View, you won’t be able to make this work.
So, this is my post for you all today. I hope you enjoyed 🙂 . I am sure there will be some alternatives. If you know any other alternative way, feel free to post is a comment. Meantime, please tell me whether this worked for you or not or compliments or criticism or anything as a comment.