0
votes

i wish to have a search form with one textbox, 2 dropdowns and a radio button (in cakephp). But this is to be done with pagination. Search and pagination work fine separately but not together. when i select the filter criteria and click on search button, the results are displyed fine on 1st page, but if i click on any of the pagination links, the filter criteria are lost and pagination data is displayed without any filter. How do i solve this? controller code:

private function _index() {
    $this->genre_list();
    $this->language_list();
    $conditions = array();
    debug($this->postConditions($this->data)); die;
    if (!empty($this->request->data['Artist'])) {
        foreach ($this->request->data['Artist'] as $name => $record) {
            if (isset($record) && !empty($record)) {
                if ($name == 'name') {
                    $conditions = array(
                        $this->modelClass->User. 'User.name LIKE' => '%' . $record . '%',
                    );
                } else {
                    $conditions[$this->modelClass . '.' . $name] = $record;
                }
            }
        }
    };

    $this->paginate = array(
        'contain' => array (
            'User' => array(

                'City',// => array('name'),
                'State',// => array('name'),
                'Country',// => array('name'),
            ),
            'Genre',// => array('name'),
            'Language',// => array('language'),
        ),
        'limit' => 3,
        'conditions' => $conditions
    );


    $data = $this->paginate($this->modelClass);
    //~ debug($data);
    $this->set(compact('data'));
}

view:

<?php
echo $this->Form->create('Search', array(
    'type' => 'file',
    'inputDefaults' => array(
        'format' => array(
            'label', 'between', 'input', 'error', 'after'
        )
    ),
    'class' => 'form-horizontal'
));
echo $this->Form->input('Artist.name', array(
    'div' => 'control-group',
    'label' => array(
        'class' => 'control-label',
        'text' => 'Artist Name'
    ),
    'between' => '<div class="controls">',
    'after' => '</div>',
    'placeholder' => 'Name',
    'error' => array(
        'attributes' => array(
            'wrap' => 'div',
            'style' => 'color:#B94A48'
        )
    )
));
echo $this->Form->input('Artist.genre_id', array(
    'div' => 'control-group',
    'empty' => 'All',
    'label' => array(
        'class' => 'control-label',
        'text' => 'Genre'
    ),
    'between' => '<div class="controls">',
    'after' => '</div>',
    'error' => array(
        'attributes' => array(
            'wrap' => 'div',
            'style' => 'color:#B94A48'
        )
    )
));

echo $this->Form->input('Artist.language_id', array(
    'div' => 'control-group',
    'empty' => 'All',
    'label' => array(
        'class' => 'control-label',
        'text' => 'Select Lanuage'
    ),
    'between' => '<div class="controls">',
    'after' => '</div>',
    'error' => array(
        'attributes' => array(
            'wrap' => 'div',
            'style' => 'color:#B94A48'


    )
        )
    ));
?>
<?php echo $this->element('pagination'); 

edited code with session

private function _index() {
    $this->genre_list();
    $this->language_list();
    $conditions = array();

    //~ foreach($this->request->params['named'] as $key => $record) {
        //~ debug($this->request->params['named']);
            //~ $this->request->data['Search'][$key] = $record;
    //~ }

    if (!empty($this->request->params['named']['page'])) {
    // use session data for conditions
    $conditions = (array)$this->Session->read('_indexConditions');
    } else {
    // delete session data
    $this->Session->delete('_indexConditions');
    }

    $conditions = array();
    if (!empty($this->request->data)) {
    // new search! use the data to make conditions,
    // like you did, and save the conditions
    //~ if (!empty($this->request->data['Artist'])) {
        foreach ($this->request->data['Search'] as $name => $record) {
            if (isset($record) && !empty($record)) {
                if ($name == 'name') {
                    $conditions = array(
                        $this->modelClass->User. 'User.name LIKE' => '%' . $record . '%',
                    );
                } else {
                    $conditions[$this->modelClass . '.' . $name] = $record;
                }
            }
        }
    //~ }
    $this->Session->write('_indexConditions', $conditions);
    }

    $this->paginate = array(
        'contain' => array (
            'User' => array(

                'City',
                'State',
                'Country',
            ),
            'Genre',
            'Language',
        ),

        'limit' => 3,
        'conditions' => $conditions
    );


    $data = $this->paginate('Artist');
    $this->set(compact('data'));
}
3

3 Answers

0
votes

The answer is pretty simple: save the search conditions in the session or cookie and use those conditions if new ones aren't sent.

For simplicity's sake, I've omitted much of your code. Something like this should work.

private function _index() {
  // check if this is a pagination request without data
  if (!empty($this->request->params['named']['page']) {
    // use session data for conditions
    $conditions = (array)$this->Session->read('_indexConditions');
  } else {
    // delete session data
    $this->Session->delete('_indexConditions');
  }

  $conditions = array();
  if (!empty($this->request->data)) {
    // new search! use the data to make conditions,
    // like you did, and save the conditions
    $this->Session->write('_indexConditions', $conditions);
  }

  $this->paginate = array(
    'conditions' => $conditions
  );
  $data = $this->paginate($this->modelClass);
  $this->set(compact('data'));
}

It should be wrapped in a component. On one of my projects I have a component that automatically does this and replaces the controller data for a more automated process.

0
votes

got the solution without using session

in controller:

if (!empty($this->request->data) || $this->request->params['named']) {
        foreach($this->request->params['named'] as $key => $record) {
            if($key!= 'page')
                $this->request->data['Search'][$key] = $record;
        }
        foreach ($this->request->data['Search'] as $name => $record) {
            if (isset($record) && !empty($record)) {
                $this->request->params['named'][$name] = $record;
                if ($name == 'name') {
                    $conditions[$this->{$this->modelClass}->User. 'User.name LIKE'] = '%' . $record . '%';
                } else {
                    $conditions[$this->modelClass . '.' . $name] = $record;
                }
            }
        }
    }

and in view provide the controller and action explicitly:

echo $this->Form->create('Search', array(
    'type' => 'file',
    'inputDefaults' => array(
        'format' => array(
            'label', 'between', 'input', 'error', 'after'
        )
    ),
    'url' => array(
        'controller' => 'artists',
        'action' => 'index',
    ),
    'class' => 'form-horizontal'
));

solves the problem.

0
votes

In 2.x, you can set your form to use GET instead of POST.

Change the type of your form from file to GET (BTW, why you use file??)

echo $this->Form->create('Search', array(
'type' => 'get',

And of course, instead of using the data array from Request

$this->request->data['Search']['name'] 

you will use the query array like this:

if (!empty($this->request->query['name'])) {