如何在symfony2中对一个控制器和存储库上的搜索结果和显示进行分页


How to paginate the search result and the display on one controller and repository in symfony2?

我目前正在使用symfony2进行一个项目。当我显示所有事务时,我有一个分页,并且在相同的控制器函数和存储库中,我还添加了搜索。我现在的问题是,如何通过将搜索结果整合到一个功能中,对搜索结果进行分页,同时显示所有交易。到目前为止,这是我所尝试的,在这段代码中分页工作得很好,但搜索结果不是。

public function getAllTransaction($rNumber,$gNumber,$senderId,$receiverId,$docType,$direction,$startDate,$endDate,$page = 1, $limit = 10) {
         $em = $this->getEntityManager();
         $query = $em->createQuery(
           'SELECT partial a.{supplierTransactionDetailId, rNumber, pNumber, invNumber, anNumber, adNumber, amount}, 
            partial b.{supplierTransactionId, transactionDate, senderId, receiverId, isaNumber, gsNumber, fileName}, 
            partial c.{supplierDocTypeId, docType, direction} 
            FROM SupplierBundle:SupplierTransactionDetail a 
            JOIN a.supplierTransaction b 
            JOIN b.supplierDocType c
            WHERE (a.rNumber LIKE :rNumber OR a.pNumber LIKE :rNumber 
                  OR a.invNumber LIKE :rNumber 
                  OR a.anNumber LIKE :rNumber 
                  OR a.adNumber LIKE :rNumber )
            AND b.gsNumber LIKE :gsNumber
            AND b.senderId LIKE :senderId
            AND b.receiverId LIKE :receiverId
            AND c.docType LIKE :docType
            AND c.direction LIKE :direction
            OR b.transactionDate BETWEEN :startDate AND :endDate
            ORDER BY b.transactionDate desc'
          )
          ->setParameter('rNumber', "%$rNumber%")
          ->setParameter('gsNumber', "%$gsNumber%")
          ->setParameter('senderId', "%$senderId%")
          ->setParameter('receiverId' , "%$receiverId%")
          ->setParameter('docType',"%$docType%")
          ->setParameter('direction', "%$direction%")
          ->setParameter('startDate', "%$startDate%")
          ->setParameter('endDate', "%$endDate%")
          ->setFirstResult(($page - 1) *$limit )
          ->setMaxResults($limit);
         $paginator = new Paginator ($query, $fetchJoinCollection = false );
         $paginator->setUseOutputWalkers(false);
         return $paginator;
      }

控制器:

public function trackAction(Request $request,$page){
        $rNumber = $request->query->get('rNumber');
        $gsNumber = $request->query->get('gsNumber');
        $senderId = $request->query->get('senderId');
        $receiverId = $request->query->get('receiverId');
        $docType = $request->query->get('docType');
        $direction = $request->query->get('direction');
        $startDate = $request->query->get('startDate');
        $endDate = $request->query->get('endDate');
        $max_records = 10;
        $em = $this->getDoctrine()->getManager();
        $trans = $em->getRepository('SupplierBundle:SupplierTransactionDetail')->getAllTransaction($rNumber,$gsNumber,$senderId,$receiverId,$docType,$direction,$startDate,$endDate,$page , 10);
        $count = $trans->count();
        $pagination = array(
            'page' => $page,
            'route' => 'supplier_tracking',
            'route_params' => array()
        );
        if ($max_records > 0 ){
            $pagination['pages_count'] = max(ceil($count / $max_records), 1);
        }
        return $this->render('SupplierBundle:Supplier:tracking.html.twig',array('trans' => $trans, 'pagination' => $pagination));

    }

谢谢。

我将试着解释我是如何解决这种情况的;我将以User实体为例。

<标题> 路由

搜索路由(/user/search, POST)

搜索表单发送它的POST数据到这个路由;在这里,我将所有带有控制器特定前缀(如app_user_filter_)的过滤器保存到会话中。

重置搜索路线(/user/search/reset,)

用于移除当前控制器会话中的所有过滤器。

List route (/user, GET)

此路由呈现用户列表并接受page参数(类似于/user?page=2)。

<标题>库h1> 的getEntities存储库方法接受一个过滤器数组(键=>值对)和一个页码;该过滤器数组是从控制器内部的会话中通过提取键以控制器特定前缀(例如,app_user_filter_emailapp_user_filter_username)开头的所有值来创建的。 <标题>结论

您的方法,在每个页面更改时,松开过滤器,因为您试图从当前请求($request->query->get('rNumber'))获得它们,但您没有将它们重新发送到更改页面url (localhost:2224/Tracker/web/app_dev.php/tracking/2)。

我的解决方案有点复杂,但有助于简化您的工作。我已经在4个项目中应用了这种解决方案,效果非常好。

如果你愿意,你可以查看我在工作中使用的包,特别是那个方法。

<标题> 例子

控制器"track"动作:

public function trackAction(Request $request, $page) {
    $filters = array();
    $prefix = 'transaction_filter_';
    $session = $request->getSession();
    foreach ($request->getSession()->all() as $key => $value) {
        if (strpos($key, $prefix) === 0) {
            $filters[str_replace($prefix, '', $key)] = $value;
        }
    }
    $repo = $this->getDoctrine()->getRepository('SupplierBundle:SupplierTransactionDetail');
    $trans = $repo->getAllTransaction($filters, $page, 10);
    // [...]
}

控制器"search"动作:

public function searchAction(Request $request)
{
    $prefix = 'transaction_filter_';
    $validFilters = array(
        'rNumber',
        'gsNumber'
        // Add the other filters to this list
    );
    $session = $request->getSession();
    foreach ($validFilters as $filter) {
        if ($request->has($filter)) {
            $session->set($prefix . $filter, $request->get($filter));
        }
    }
    // Redirect to the trackAction url
}

控制器"reset search"动作:

public function resetSearchAction(Request $request)
{
    $prefix = 'transaction_filter_';
    $session = $request->getSession();
    foreach ($request->getSession()->all() as $key => $value) {
        if (strpos($key, $prefix) === 0) {
            $session->remove($key);
        }
    }
    // Redirect to the trackAction url
}

库方法:

public function getAllTransaction($filters, $page, $elementsPerPage)
{
    $queryBuilder = $this->createQueryBuilder('a')
        ->addSelect('b, c')
        ->from('SupplierBundle:SupplierTransactionDetail', 'a')
        ->join('a.supplierTransaction', 'b')
        ->join('b.supplierDocType', 'c')
        ->addOrderBy('b.transactionDate', 'desc')
        ->setFirstResult(($page - 1) * $elementsPerPage )
        ->setMaxResults($elementsPerPage);
    foreach ($filters as $filter => $value) {
        if ($filter == 'rNumber') {
            $queryBuilder->andWhere(
                $queryBuilder->expr()->orX(
                    $queryBuilder->expr()->like('a.rNumber', $value),
                    $queryBuilder->expr()->like('a.pNumber', $value),
                    $queryBuilder->expr()->like('a.invNumber', $value),
                    $queryBuilder->expr()->like('a.anNumber', $value),
                    $queryBuilder->expr()->like('a.adNumber', $value)
                )
            );
        }
        if ($filter == 'gsNumber') {
            $queryBuilder->andWhere('b.gsNumber = :gsNumber')->setParameter('gsNumber', $value);
        }
        // Add the other filters here
    }
    return new Paginator($queryBuilder);
}