简体   繁体   中英

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

I am currently working on a project using symfony2. I have a pagination when I display all the transaction and in the same controller function and repository I also add search. My problem now is on how can I paginate my search result and the same time my display for all transaction, by just consolidating it in one function,... So far here is what I tried, the pagination is working perfectly in this code but the search result is not.

Repository

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;
      }

Controller :

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));


    }

Thanks ahead .

I'll try to explain how I solved this situation; I'll use the User entity as an example.

Routing

Search route ( /user/search , POST)

The search form sends its POST data to this route; here I save into the session all the filters with a controller-specific prefix (something like app_user_filter_ ).

Reset search route ( /user/search/reset , GET)

Used to remove all the filters from the session for the current controller.

List route ( /user , GET)

This route renders the users list and accept a page parameter (something like /user?page=2 ).

Repository

My getEntities repository method accepts an array of filters (as key => value pairs) and a page number; that array of filters is created from the session inside the controller by extracting all the values whose key starts with my controller-specific prefix (for example, app_user_filter_email or app_user_filter_username ).

Conclusions

Your method, on each page change, loose the filters because you try to get them from the current request ( $request->query->get('rNumber') ) but you do not re-send them into the change page url ( localhost:2224/Tracker/web/app_dev.php/tracking/2 ).

My solution is a bit complex but helps to streamline your work. I've applied this kind of solution into 4 projects already, and it works like a charm.

If you want you can check out the bundle I use at work , expecially that method .

Example

Controller "track" action:

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);

    // [...]
}

Controller "search" action:

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
}

Controller "reset search" action:

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
}

Repository method:

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM