我的ZF2应用程序中有一个模块Search
。用户填写搜索表单并获取课程列表。
现在我将分页添加到模块中。分页器基本上工作:我可以通过它检索数据并正确显示分页(70页找到的课程的页面链接1-7,dafault设置每页10项)。
但它仍然无法使用。单击页面链接时,表单POST数据将丢失。我知道 - 它无法正常工作,我是如何实现的(参见下面的代码)。但我不知道,如何正确地做到这一点,以便检查表单数据,但仍然可以使用分页。
那是我的代码:
表类Search \ Model \ CourseTable
class CourseTable {
...
// without pagination
// public function findAllByCriteria(CourseSearchInput $input) {
// with pagination
public function findAllByCriteria(CourseSearchInput $input, $pageNumber) {
...
$select = new Select();
$where = new Where();
$having = new Having();
...
// without pagination
// $resultSet = $this->tableGateway->selectWith($select);
// return $resultSet;
// with pagination
$adapter = new \MyNamespqce\Paginator\Adapter\DbSelect($select, $this->tableGateway->getAdapter());
$paginator = new \Zend\Paginator\Paginator($adapter);
$paginator->setCurrentPageNumber($pageNumber);
return $paginator;
}
...
}
搜索\控制器\ SearchController
class SearchController extends AbstractActionController {
public function searchCoursesAction() {
$form = $this->getServiceLocator()->get('Search\Form\CourseSearchForm');
$request = $this->getRequest();
if ($request->isPost()) {
$courseSearchInput = new CourseSearchInput();
$form->setInputFilter($courseSearchInput->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$courseSearchInput->exchangeArray($form->getData());
// without pagination
// $courses = $this->getCourseTable()->findAllByCriteria($courseSearchInput);
// with pagination
$page = $this->params()->fromRoute('page');
$paginator = $this->getCourseTable()->findAllByCriteria($courseSearchInput, $page);
} else {
$paginator = null;
}
} else {
$paginator = null;
}
return new ViewModel(array(
'form' => $form,
// without pagination
// 'courses' => $courses,
// with pagination
'paginator' => $paginator,
'cities' => ...
));
}
...
}
如何让它运作?
答案 0 :(得分:1)
我也有同样的问题,我已经解决了。但这不是好方法。可能是这个想法会对你有帮助。
我解决了它如下:(搜索Zend教程相册模块的分页)
我在控制器中构建了两个名为“search”和“index”的动作。
每当提交搜索表单时,它始终将值发布到搜索操作。搜索操作使用搜索参数构建URL,并重定向到索引以显示搜索结果。
点击分页链接后,发布的值会通过网址传递。因此,每当索引操作请求搜索参数时,它总是以相同的格式获取值。
我将路线定义如下:
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/:action][/:id][/page/:page][/order_by/:order_by][/:order][/search_by/:search_by]',
'constraints' => array(
'action' => '(?!\bpage\b)(?!\border_by\b)(?!\bsearch_by\b)[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
'page' => '[0-9]+',
'order_by' => '[a-zA-Z][a-zA-Z0-9_-]*',
'order' => 'ASC|DESC',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
有一个名为“search_by”的参数,它将所有搜索参数保存为json字符串。这是重点,我知道这不好,但还没有找到任何其他方法。
“搜索”操作将此字符串构建为 -
public function searchAction()
{
$request = $this->getRequest();
$url = 'index';
if ($request->isPost()) {
$formdata = (array) $request->getPost();
$search_data = array();
foreach ($formdata as $key => $value) {
if ($key != 'submit') {
if (!empty($value)) {
$search_data[$key] = $value;
}
}
}
if (!empty($search_data)) {
$search_by = json_encode($search_data);
$url .= '/search_by/' . $search_by;
}
}
$this->redirect()->toUrl($url);
}
下一个索引操作解码字符串,执行必要的操作,并发送json字符串进行查看。
public function indexAction() {
$searchform = new AlbumSearchForm();
$searchform->get('submit')->setValue('Search');
$select = new Select();
$order_by = $this->params()->fromRoute('order_by') ?
$this->params()->fromRoute('order_by') : 'id';
$order = $this->params()->fromRoute('order') ?
$this->params()->fromRoute('order') : Select::ORDER_ASCENDING;
$page = $this->params()->fromRoute('page') ? (int) $this->params()->fromRoute('page') : 1;
$select->order($order_by . ' ' . $order);
$search_by = $this->params()->fromRoute('search_by') ?
$this->params()->fromRoute('search_by') : '';
$where = new \Zend\Db\Sql\Where();
$formdata = array();
if (!empty($search_by)) {
$formdata = (array) json_decode($search_by);
if (!empty($formdata['artist'])) {
$where->addPredicate(
new \Zend\Db\Sql\Predicate\Like('artist', '%' . $formdata['artist'] . '%')
);
}
if (!empty($formdata['title'])) {
$where->addPredicate(
new \Zend\Db\Sql\Predicate\Like('title', '%' . $formdata['title'] . '%')
);
}
}
if (!empty($where)) {
$select->where($where);
}
$album = $this->getAlbumTable()->fetchAll($select);
$totalRecord = $album->count();
$itemsPerPage = 2;
$album->current();
$paginator = new Paginator(new paginatorIterator($album));
$paginator->setCurrentPageNumber($page)
->setItemCountPerPage($itemsPerPage)
->setPageRange(7);
$searchform->setData($formdata);
return new ViewModel(array(
'search_by' => $search_by,
'order_by' => $order_by,
'order' => $order,
'page' => $page,
'paginator' => $paginator,
'pageAction' => 'album',
'form' => $searchform,
'totalRecord' => $totalRecord
));
}
所有排序和分页网址都包含该字符串。
如果你之前知道所有的搜索参数,那么你可以在路由中定义它,并且在没有json字符串的情况下以相同的方式传递。由于我必须构建一个通用搜索,我已经构建了一个字符串。
“相册搜索”的源代码可在https://github.com/tahmina8765/zf2_search_with_pagination_example的git hub中找到。
答案 1 :(得分:1)
@Sam& @automatix在问题评论中都是对的。我的建议(虽然我正在寻找一个更简单的替代方案)是构建一个段路由,它涵盖了您可能需要的所有选项,并以标准表单POST请求开始。
然后,在验证请求后,将表单数据传递给paginationControl助手,如下所示:
$resultsView = new ViewModel(array(
'paginator' => $paginator,
'routeParams' => array_filter($form->getData())
));
然后,在视图模板中,在paginationControl视图助手中设置路由参数:
<?php echo $this->paginationControl($paginator, 'Sliding', 'paginator/default',
array('routeParams' => $routeParams)
) ?>
我在这里使用了array_filter,因为它是从表单数据中删除任何元素的一种非常简单的方法,即空,空等等。这样你就不会传递你不需要的额外数据。