I have the following method which takes a query to search my notes:
function search( $q = null )
{
if ( $q == null )
{
$this->redirect(array('action' => 'index'));
}
$this->paginate = array(
'limit'=>5,
'order'=>'Note.datetime DESC',
'conditions' => array(
'OR' => array(
'Note.title LIKE' => '%'. $q . '%',
'Note.content LIKE' => '%'. $q . '%'
)
),
'Note.status'=>1
);
$this->set('notes', $this->paginate());
$this->render('index');
}
As you can see it takes a single parameter called 'q' which is used to query the model data.
I have hooked up this to the router like so:
Router::connect('/notes',
array('controller'=>'notes','action'=>'index', 'page' => 1),
array(
'pass' => array('page')
)
);
Router::connect('/notes/page/:page',
array('controller' => 'notes', 'action' => 'index'),
array(
'pass' => array('page'),
'page' => '[1-9]+'
)
);
Router::connect('/notes/search/:page/:q',
array('controller'=>'notes','action'=>'search', 'page' => 1),
array(
'pass' => array('page','q')
)
);
Router::connect('/notes/search/:q/page/:page',
array('controller' => 'notes', 'action' => 'search'),
array(
'pass' => array('page','q'),
'page' => '[1-9]+'
)
);
This way I should be getting urls like:
domain.com/notes - loads page 1 of notes
domain.com/notes/page/2 - loads page 2 of notes
domain.com/notes/search/Hello - searches for Hello in notes
domain.com/notes/search/Hello/page/2 - shows page 2 of the above search
The pager in the view looks like:
<?php if(isset($this->request->params['named']['q'])) { ?>
<?php $this->Paginator->options(array('url'=>array('controller' => 'notes', 'action' => $action, 'q' => $this->request->params['named']['q']))); ?>
<?php } else { ?>
<?php $this->Paginator->options(array('url'=>array('controller' => 'notes', 'action' => $action))); ?>
<?php } ?>
It works fine for the index method, but for the search method it is getting confused as when I do a search it's not matching the pager with the route as expected. For example I'm getting urls like domain.com/notes/search/2/:q
Also I don't really like having to wrap the paginator options in an if statement so if I can get it to figure out the url automatically that would be awesome as it's messy having to do this and seems to be the cause of the above problems.
I have connected the named parameter at the top of the router like so:
Router::connectNamed(array('q'));
In the end I opted to make my search working using POST instead of GET so that everything is handled sever-side instead of doing it with messy url rewrites and trying to be clever.
Here's what I made the form look like:
<?php echo $this->Form->create('search', array('url'=>array('controller'=>'notes','action'=>'search'),'class'=>'search')); ?>
<label class="placeholder" for="q">Search</label>
<?php if( isset($q) ) { $term = $q; } else { $term = ''; } ?>
<?php echo $this->Form->input('q', array('label'=>false,'id'=>'q','value'=>$term)); ?>
<button type="submit" class="btn ss-icon ss-search"></button>
<?php echo $this->Form->end(); ?>
the search method:
function search()
{
if ($this->request->is('post')) {
$this->Session->write('q', $this->request->data['search']['q']);
$this->redirect(array('action' => 'search'));
} else {
$q = $this->Session->read('q');
$this->paginate = array(
'limit'=>5,
'order'=>'Note.datetime DESC',
'conditions' => array(
'OR' => array(
'Note.title LIKE' => '%'. $q . '%',
'Note.content LIKE' => '%'. $q . '%'
)
),
'Note.status'=>1
);
$this->set('q',$q);
$this->set('action','search');
$this->set('notes', $this->paginate());
$this->render('index');
}
}
and the routes:
Router::connect('/notes/search',
array('controller'=>'notes','action'=>'search', 'page' => 1),
array(
'pass' => array('page')
)
);
Router::connect('/notes/search/page/:page',
array('controller' => 'notes', 'action' => 'search'),
array(
'pass' => array('page'),
'page' => '[1-9]+'
)
);
and I clean up the session if any other page but the search method is being used in the AppController:
if(strpos($this->here, Router::url(array('controller'=>'notes','action'=>'search'))) === 0 ) {
//echo 'yes';
} else {
$this->Session->delete('q');
}
Which gives me urls like:
domain.com/notes
- loads page 1 of notes
domain.com/notes/page/2
- loads page 2 of notes
domain.com/notes/search
- searches for Hello in notes (stored in session)
domain.com/notes/search/page/2
- shows page 2 of the above search