I am using Zend\Paginator to construct a paginated result set. This works fine, however, after adding a search form, I cannot get the two to play nicely together.
The URL produced by the search form on the page is:
user/index/?searchTerm=hello
How do I amend the Zend paginator configuration so that it retains the searchTerm in the URLs produced?
I was hoping for something like:
user/index/page/4/?searchTerm=hello
What am I missing?
The module config route is defined as follows:
'user' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/user[/[:action[/]]][[id/:id]][/[page/:page]]',
'defaults' => array(
'controller' => 'Application\Controller\User',
'action' => 'index',
'id' => null,
),
// the below was added to try and get the searchTerm query to be retained
'may_terminate' => true,
'child_routes' => array(
'searchTerm' => array(
'type' => 'Query',
),
),
),
),
The pagination is constructed using this in the view:
echo $this->paginationControl(
$this->users, 'sliding', array('paginator', 'User'), array('route' => 'user', 'action' => 'index')
);
Pagination template snippet:
<li>
<a href="<?php echo $this->url($this->route, array('action' => $this->action, 'page' => $this->next), true); ?>">
Next »
</a>
</li>
(I was under the impression that passing true
as the third parameter to url()
would retain the query params.)
I now see what that third parameter to url()
is doing. I can simplify the pagination links and remove the 'action' key as follows:
<a href="<?php echo $this->url($this->route, array('page' => $this->next), true); ?>">
The page's action was matched as part of the URL (due to that third param being true) which is why that works. By the same token I can change the route to this:
'route' => '/user[/[:action[/]]][[id/:id]][/[page/:page]][/[search/:search]]',
And then the search
will be retained in the pagination links.
If I amend the search form to submit via JavaScript, I can construct the search URL and direct the user to it.
Simple jQuery example for that approach:
$(".search-form").submit(function() {
var baseUrl = $(this).attr('action'),
search = $(this).find('.search').val();
window.location = baseUrl + '/search/' + search;
return false;
});
Another option would be to redirect to the current/route/search/term
route in the controller if it receives a searchTerm query.
I'm posting this as an answer but I am open to better solutions.