Cake PHP Search Component [Updated:22:05:2012]


Cake PHP Search Component :

hiiiiiii Guys ! Cake Php Search Component is used to implement search in your cake php projects.The component provide highly reusability. component is meant to use across all the controllers. you just include this search component in your Controller and call a component function to fetch your conditions types in search form and refine the data .

This Search Component will get the search parameters passed in search form and then generate the conditions t refine your search .Then conditions returned by the Search Component will be further passed to paginate and the result will be filtered according to the conditions .

Download Component CakePHP 1.3

Download Component CakePHP 2.0

The searching in cakePHP is not that hard .so just follow the steps and i am sure that you can easily implement searching in cake php.

So we lets move on and take a look a t The implementation of the cake Php Search Component in your project.

Step1:(Copy  search Component in components Folder):

So the first step is that you download the search component From the link above and then Copy it in the Components folder

that is Copy the search.php in

C:\xampp\htdocs\dpm\app\controllers\components\
Step2:(include Search Component in your Controller ):

So now we have copied our Search  Component in the Component’s folder .now we include it in our controller on which we want to implement the cake php search.

So to use this cake php search we tell our controller to load the this search component from components folder.To do this we add a little one line code in our controller.here it is:

var $components=array('Search');
public $components=array('Search');

The code above will tell cake php Controller to  include this search component in the current controller.So now we move on to next step:

Step 3:(Create Generic  Search element  and pagination element ):

After including the search component to our controller we move on and create a search form element. So that the form will be usable across various views of the all controller in our application.

here is the search form element  for this component

C:\xampp\htdocs\your app name\app\views\elements\searchForm\form.ctp
</pre>
<div class="search" style="margin: 10px;">
<fieldset>
<h2>Search <!--?php echo$this--->params['controller'] ?></h2>

<hr />

<!--?php echo $form--->create(array('action' => 'index', 'type' => 'GET')); ?>
 <!--?php  $name = isset($this--->params['url']['name']) ? $this->params['url']['name'] : null;
 echo $form->input('id', array('div' => false, 'label'=>'Search by id','type'=>'text'));
 echo $form->input('name', array('div' => false, 'label'=>'Search by name','value'=>$name));
 echo $form->submit('Search',array('class'=>'button'));
 ?>

<!--?php echo$form--->end(); ?></fieldset>
</div>
<pre>


</pre>
<div class="search" style="margin: 10px;">
<fieldset>
<h2>Search <!--?php echo$this--->params['controller'] ?></h2>

<hr />

<!--?php echo $this--->Form->create(array('action' => 'index', 'type' => 'GET')); ?>
 <!--?php  $name = isset($this--->params['url']['name']) ? $this->params['url']['name'] : null;
 echo $this->Form->input('id', array( 'label'=>'ID','type'=>'text'));
 echo $this->Form->input('name', array('label'=>'Name','value'=>$name));
 echo $this->Form->submit('Search',array('class'=>'button'));
 ?>

<!--?php echo $this--->Form->end(); ?></fieldset>
</div>
<pre>


Now In order to make search component work fine with the pagination we create another element called set_pagination_named.ctp file .

C:\xampp\htdocs\your app name\app\views\elements\searchForm\set_pagination_named.ctp:

(Same For cakePHP 1.3 and CakePHP 2.0)

This element will check the search condition in the search component and pass them on to paginator options so that paginator works fine with the search component.As the params has some extra field in it like extention,controller,action so we check in array the valid fields is passed.

<!--?php $data_arr=array(); if(isset($this--->params['url']) || isset($this->params['named'])){
$data=isset($this->params['named'] ) && !empty($this->params['named']) ? $this->params['named']:$this->params['url'];
 $possibledata=array('name','id');//possible fields
 foreach($data as $key=>$value){
 if(in_array($key,$possibledata) && !empty($value)){
 $data_arr[$key]=$data[$key];
 }
 }

}
?>
<!--?php $this--->Paginator->options(array(
 'evalScripts' => true,
 'url'=>$data_arr
));
?>
Step 4:(Create controller Action ):

(Same For cakePHP 1.3 and CakePHP 2.0)

Our Next step is to create a controller action where we gonna implement search.Say in our index action we wana add search logic.So to do so we create a index action in our controller . for example we say in our pages controller we create index action

So we gonna paste the code below in our controller’s index action

function index() {
$this->Page->recursive = 0;
 $conditions=$this->Search->getConditions();
$this->set('pages', $this->paginate(null,$conditions));
 }

The above code at first load of the page will show you all the pages and when the search query is typed in search form then it will get those search conditions via the search component’s getConditions method.if search form is not used then it will show all the results.

Well that was easy you just need to type in a single line to get all the conditions .The search component will fetch all the condition and gets the appropriate result.

But there is one step still left .we also need to create a index.ctp file which is cake php template file for the index action.So before using the search we move on and create index.ctp.

Step5 ( Create index.ctp for the index action ):

The next step is to create a Index.ctp file for our controller action.we will include our search form in the this index.ctp and also the set_pagination_named.ctp element is also included here.

So i might be clear to you that whenever we wana use this search in any action we gonna include these two elements in its view.So it is pretty simple.

index.ctp:

In this index.ctp file all the code is generated by bake console we just added two elements  ’search form’ and also ‘set pagiation named.ctp’ .So do not need to worry about whole code.

</pre>
<div class="pages index"><!--?php echo $this--->element('searchForm/set_pagination_named');?>//set pagination named element
 <!--?php echo $this--->element('searchForm/form') ?>//search form element
<h2></h2>
<tr>
Html->link(__('Edit', true), array('action' => 'edit', $page['Page']['id'])); ?>
Html->link(__('Delete', true), array('action' => 'delete', $page['Page']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $page['Page']['id'])); ?>
<table cellspacing="0" cellpadding="0">
<tbody>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
<th class="actions"></th>
</tr>
<!--?php  $i = 0;  foreach ($pages as $page):  $class = null;  if ($i++ % 2 == 0) {  $class = ' class="altrow"';  }  ?--><!--?php echo $class;?--><!--?php echo $page['Page']['id']; ?--><!--?php echo $page['Page']['name']; ?--><!--?php echo $page['Page']['active']; ?--> <!--?php echo $this---> <!--?php echo $this---><!--?php endforeach; ?--></tbody>
</table>
 <!--?php  echo $this--->Paginator->counter(array(
 'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)
 ));
 ?>
<div class="paging"><!--?php echo $this--->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
 | <!--?php echo $this--->Paginator->numbers();?>
 |
 <!--?php echo $this--->Paginator->next(__('next', true) . ' >>', array(), null, array('class' => 'disabled'));?></div>
</div>
<pre>

So That is all the search component .after doing this check your search ,it will work fine.After completing all these steps  you have successfully implemented your search in cake php project.download the component from below.

Search Component CakePHP1.3

Download Component

Search Component CakePHP2.0

Download Component

Thanks for visiting designaeon.Please hit like and do share this post if you like it

Posted Under Categories:
More Stuff About:

About the author

Ramandeep Singh Is Btech Graduate in Computer Science.He has interest in Programming.He knows .net ,vb.net,c#.Ramandeep Singh is certified web developer in PHP and PHP Framework(cakePHP).Ramandeep Likes to write Tutorials on Blog,that is why he founded DesignAeon

35 Responses to Cake PHP Search Component [Updated:22:05:2012]

      • richa
      • Following error is coming by including Serch component as per your steps:-
        1)Call to a member function create() on a non-object
        2)File: C:\xampp\htdocs\dlwadmin\app\View\Elements\form.ctp

  1. Pingback: OTHER CHANGES « ruben cakephp coursework progress

  2. Pingback: ruben cakephp coursework progress

  3. Pingback: Search Bar « USCMS, DWT, 2nd Assignment

    • lily
    • I got error:
      all_user_func_array() expects parameter 1 to be a valid callback, class ‘SearchComponent’ does not have a method ‘startup’ [CORE\Cake\Utility\ObjectCollection.php, line 103]

    • Ramandeep Singh
    • Lily You are Using CakePHP 2.0 I guess. So i have made a few changes,Please Download the New Component i made for cakePHP 2.0:
      http://www.designaeon.com/downloads/search2.0.rar

      And read the changes For the cakePHP 2.0 as i have updated this post today ,now it is fully compatible with cakePHP 2.0 .Please ask if any problem found..

    • Lily
    • Very nice, Now it works.
      thanks for your help :)

      Just change this element(‘searchForm/setting_pagination_named’);?>//set pagination named element

      In your element, the pagination name is ‘set_pagination_named’

      Thanks again

    • Manuel
    • Hi. I’m trying to change your SearchComponent.php I need to search a field with > and another with < for example. Both are integer. How can I solve this problem??? Thanks! Where can I insert a field definition of my sql db?

      • Manuel
      • well sort of. and another search is: price not more than …, rooms more than …, etc…
        Do you understand my problem?

        • Ramandeep Singh
        • Inside the Switch “integer case” you could check your Custom parameters if they are set and build a condition according to that.
          Example You have to get posts between id 1-15 You simply check your set range params inside the “Integer case” .Also when the range is set you also have to make sure that the column name you are applying range is also set cause if it is not set then the you won’t be able to reach the integer case.
          Means you are applying range to “id” field than make sure “id” is set and then check the range parameters set inside the “integer case” .or you can send your range params as same name of the column.
          I hope you understand it.

          • Manuel
          • Can’t follow you till the end. Here’s the code:
            function getConditions(){
            $conditions = array();
            $data= empty($this->controller->params['named']) ? $this->controller->params['url'] : $this->controller->params['named'] ;
            $this->controller->{$this->controller->modelClass}->schema();
            foreach($data as $key=>$value){
            if(isset($this->controller->{$this->controller->modelClass}->_schema[$key]) && !empty($value)){
            switch($this->controller->{$this->controller->modelClass}->_schema[$key]['type']){
            case “string”:
            $conditions[$this->controller->modelClass . "." .$key. " LIKE"] = “%”.trim($value).”%”;
            break;
            case “integer”:
            $conditions[$this->controller->modelClass . "." .$key. " >"] = $value;
            break;
            case “date”:
            if(isset($this->controller->params['named'][$key."_fromdate"])){
            $from = date(“Y-m-d”, strtotime( $this->controller->params['named'][$key."_fromdate"] ));
            $conditions[$this->controller->modelClass.".".$key." >="] = trim($from);
            }
            if(isset($this->controller->params['named'][$key."_todate"])){
            $to = date(“Y-m-d”, strtotime($this->params['named'][$key."_todate"]));
            $conditions[$this->controller->modelClass.".".$key." <="] = $to;
            }
            }
            }
            }
            return $conditions;

            I changed the params for integer. Now I want to search inside my model "Deal" and inside the table in rows "rooms", "price". rooms is more than x and price is less than y. Both are integer?!?

            • Ramandeep Singh
            • Take a look :-

              case “integer”:
              //You could Check Your Range params here.
              /*
              check your range parameteres here.you can use debug($this->-controller->params) to check the params .if params are set then have an if statement ,inside that build your condition ,in else do the defalut behavior
              Eg.
              if(isset($this->controller->params['named']['from_price'])){
              //build your conditions here
              }
              else
              {
              $conditions[$this->controller->modelClass . "." .$key] = $value;
              }

              */
              $conditions[$this->controller->modelClass . "." .$key] = $value;

              break;

              find the complex find condition here:
              http://book.cakephp.org/1.3/en/view/1030/Complex-Find-Conditions

    • Manuel
    • Thats my debug result:
      object(CakeRequest) {
      params => array(
      ‘plugin’ => null,
      ‘controller’ => ‘deals’,
      ‘action’ => ‘index’,
      ‘named’ => array(),
      ‘pass’ => array(),
      ‘isAjax’ => false
      )
      data => array()
      query => array(
      ‘zimmer’ => ’0′,
      ‘wohnflaechemin’ => ’200′,
      ‘kaufpreis’ => ’500000′
      )
      url => ‘deals’
      base => ‘/cms’
      webroot => ‘/cms/’
      here => ‘/cms/deals’
      }

    • Cristian
    • Hi Ramandeep, my code isn´t working, could you explain me again the steps 4 and 5 (i mean the folders were this codes must be included)

      Thanks in advance

    • Eliza
    • This is awesome!! Effective, lightweight, easy to understand, easy to modify, and your super-clear instructions are much appreciated. Thank you so much!

    • stevie
    • Great utility – but can it be used against more than one field?
      I’m similar to Manuel, but I need to search across more than one string field.
      I assume I need to change this part of SearchComponent.php
      case "string":
      $conditions[$this->controller->modelClass . "." .$key . " LIKE"] = "%".trim($value)."%";

      But I am a little unsure as to the syntax.
      The alternative I suppose is to make a database view and contatenate several fields into one, and search on that.

    • Bernie
    • Hi Ramandeep,

      Thanks for the nice work!

      I patched your Cake PHP Search Component for cakepahp 2.0 to handle better non-named url params of type date. Furthermore I added some comments / instructions and whitespace to the code.

      I just emailed you the patched code for the Search Component, to that you can publish an update here.

      cheers,
      Bernie

    • Edgar
    • Why so complex to understand? Why can’t you tell what index.ctp files we need to create? Explain 4 and 5 steps.

      • Ramandeep Singh
      • Edgar Its The Your controller action….In this Step 4 and 5 i have created index action ,which is index funciton,,,in cakePHP if i create function index() then i’ll create index.ctp for that too..Its that simple Eg.
        Say You have controller named songs ,,,,their is function index(){} and you will create index.ctp in “app/views/songs/index.ctp”

    • Cristian
    • This pluging it´s working very good!!! thanks!!!

      I noted that pluging always return all the values from the database when you enter in the page.ctp of the application, could you tell me how do i change the code to not return any value when i go in the page? i would like to search the values by myself.

      Regards

    • Siva sankar
    • Thanks Ramandeep Singh , this code worked for me at first attempt !!!!!!!!!
      Its working for belongsTo associations { ex :product search by category id } .
      I need to search hasAndBelongsToMany associations {many to many relation ship} .

  4. Pingback: Post – index.ctp | Gregor Brown's dynamic web technology blog.

    • Hussain
    • Hello Ramandeep, thanks for the code. I’ve tried to implement it, however i’m having this error, as well as some others, but i figure i would be able to solve the other problems if this is solved.

      Error : Indirect modification of overloaded property MyControllerController::$Page has no effect

      Any idea on why this is happening, i’ve followed all the steps thoroughly. Thanks again ;)

    • p0wder
    • Hi.
      I implemented your search component but I have a few problems. At first Cake didn’t recognize the component. After I renamed search.php in SearchComponent.php I got another Error: Declaration of SearchComponent::initialize() should be compatible with Component::initialize(Controller $controller) [APP/Controller/Component/SearchComponent.php, line 40]

      I didn’t change search.php except for the filename.

Leave a Reply