Last active
March 19, 2021 08:59
-
-
Save ianef/cdc445fe0df33c7dd7b7be3e8a16f866 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Controller; | |
use App\PaginatorSSP; | |
use Doctrine\ORM\EntityManagerInterface; | |
use JMS\Serializer\SerializerInterface; | |
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |
use Symfony\Component\Routing\Annotation\Route; | |
use Symfony\Component\HttpFoundation\Response; | |
/** | |
* Sample controller class to demonstrate server side processing. | |
* | |
* @author Ian Foulds <ianfoulds@x-act.co.uk> | |
*/ | |
class SampleController extends AbstractController | |
{ | |
/** | |
* Sample controller action to demonstrate PaginatorSSP | |
* | |
* @Route("/my-data-list", name="my_data_list", options={"expose"=true}) | |
*/ | |
public function dataList(EntityManagerInterface $em, SerializerInterface $serializer, PaginatorSSP $paginator): Response | |
{ | |
$filter = $paginator->getFilter(); | |
$totalRecords = $em->createQuery( | |
'SELECT COUNT(e.id) FROM MyEntity e' | |
) | |
->getSingleScalarResult(); | |
$dql = 'SELECT e FROM MyEntity e WHERE CONCAT(e.field1, e.field2, e.field3) LIKE :filter'; | |
$dql .= $paginator->getOrderBy('e'); | |
$query = $em->createQuery($dql)->setParameters([filter' => $filter]); | |
$paginator->setLimits($query); | |
return new Response( | |
$serializer->serialize($paginator->getResults($totalRecords, false), 'json') | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App; | |
use Doctrine\ORM\Query; | |
use Doctrine\ORM\Tools\Pagination\Paginator; | |
use InvalidArgumentException; | |
use Symfony\Component\HttpFoundation\RequestStack; | |
/** | |
* Helper class for providing simple pagination server side processing. | |
* It provides pagination only, the search filter needs to be applied | |
* to the DQL before passing to the this class for applying pagination. | |
* | |
* @author Ian Foulds <ianfoulds@x-act.co.uk> | |
*/ | |
class PaginatorSSP | |
{ | |
/** @var Request */ | |
protected $request; | |
/** @var Query */ | |
protected $query = null; | |
/** | |
* Constructor | |
*/ | |
public function __construct(RequestStack $requestStack) | |
{ | |
$this->request = $requestStack->getCurrentRequest(); | |
} | |
/** | |
* Return the filter string from the query, or % if empty. | |
*/ | |
public function getFilter(): string | |
{ | |
$filter = $this->request->query->get('filter') ?? null; | |
return ($filter == null ? '%' : "%{$filter}%"); | |
} | |
/** | |
* Return the ORDER BY DQL clause | |
* | |
* @param string|Array $tablePrefix String prefix for all columns, or an array of columnName => prefix values | |
*/ | |
public function getOrderBy($tablePrefix): string | |
{ | |
$orderBy = $this->request->get('orderBy', null); | |
$orderByDql = ''; | |
if ($orderBy) { | |
$orderByDql = ' ORDER BY '; | |
$direction = (substr($orderBy, 0, 1) == '-' ? 'DESC' : 'ASC'); | |
$col = ltrim($orderBy, ' -'); | |
$prefix = is_array($tablePrefix) ? $tablePrefix[$col] : $tablePrefix; | |
$orderByDql .= "{$prefix}.{$col} {$direction} "; | |
} | |
return rtrim($orderByDql, ', '); | |
} | |
/** | |
* Set the limits for the query | |
*/ | |
public function setLimits(Query $query): Query | |
{ | |
$this->query = $query; | |
$this->query->setFirstResult($this->request->get('pageStart')); | |
$this->query->setMaxResults($this->request->get('pageLength')); | |
return $this->query; | |
} | |
/** | |
* Return the resultant array for the Paginator SSP results. | |
* The totalCount parameter should be the total records prior to applying any filter (search). | |
* The returned filteredCount is the total number of records available after the filter has been applied. | |
* The actual number of records returned is determined by the request length parameter and the number of result rows available. | |
* | |
* @throws InvalidArgumentException | |
*/ | |
public function getResults(int $totalCount, bool $fetchJoinCollection = true): PaginatorResults | |
{ | |
if (!$this->query) { | |
throw new InvalidArgumentException('The query must be applied in PaginatorSSP by calling setLimits() before calling getResults().'); | |
} | |
$paginator = new Paginator($this->query, $fetchJoinCollection); | |
$filteredCount = count($paginator); | |
$results = $this->query->getResult(); | |
return new PaginatorResults(count($results), $totalCount, $filteredCount, $results); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment