0
votes

I want a simple search feature that can search the current selected results on the model's index page. I have created a model Search which has no actual table:

class Search extends AppModel {

protected $_schema = array(
    'search_term' => array('type' => 'string' , 'null' => true, 'default' => '', 'length' => '255'),
    'model' => array('type' => 'string' , 'null' => true, 'default' => '', 'length' => '255'),
);
public $useTable = false;
public $validate = array(
    'search_term' => array(
        'notEmpty' => array(
            'rule' => array('notEmpty'),
            'message' => 'Please enter a search term'
        ),
        'between' => array(
            'rule' => array('between',3,30),
            'message' => 'Please enter a search term greater than 3 characters.'
        )
    )
);

}

In any index.ctp view I have this with a hidden input field with the model's name:

echo $this->Form->create('Search, array('action' => 'search'));
    echo $this->Form->input('search_term', array('label'=> 'Search'));
    echo $this->Form->input('model', array('type'=> 'hidden', 'value'=>$this->params['controller']));
    echo $this->Form->end(__('Submit'));    

In the SearchesController:

public function search() {
$conditions = null;
if( $this->request->is('post') ) {
        $searchModel = $this->request->data[$this->modelClass]['model'];
        ...
        $this->{$this->modelClass}->useTable = Inflector::tableize($searchModel);
    ...
    $this->paginate = array('conditions'=>array($groups,'OR' => $conditions));
    $this->set($searchModel, $this->paginate());
    $this->render("/$searchModel/index");   
}

Problem is paginate is returning an array with the model labelled as 'Search' (understandably because of the useTable call) and not say Groups or Users, the model's being searched. Any way to relabel the array returned from paginate to the model being searched ? The alternative is to modify all the index.ctp files or create a results.ctp for each model.

1
Why hacking it together yourself? Embrace the functionality that is already available (and in a clean and DRY approach): github.com/CakeDC/search - it uses PRG and good conventions you should use. It also makes it so much simplier to add search functionality to any of your controllers.mark
Yeah, I saw that but it looked complicated... I've done a search already with one function in AppController and then just drop the search box/element in any index page, with the index page then reused for results.trafalgar
Its 3 lines of code. thats not more complicated than what you are trying to do :)mark

1 Answers

1
votes

I wouldn’t create another model merely for searching; it’s a hack and not extendable.

In the past, I’ve just used parameters (usually in the query string) to alter the conditions array (whether it’s a normal find operation of a paginate operation). An example:

<?php
class ItemsController extends AppController {

    public function index() {
        $conditions = array();

        if (isset($this->request->query['search'])) {
            $conditions['Item.title'] = $this->request->query['search'];
        }

        $items = $this->Item->find('all', array(
            'conditions' => $conditions
        ));

        $this->set(compact('items'));
    }
}

Hopefully the above demonstrates this approach.