Skip to content

Instantly share code, notes, and snippets.

@ianef
Last active March 19, 2021 08:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ianef/cdc445fe0df33c7dd7b7be3e8a16f866 to your computer and use it in GitHub Desktop.
Save ianef/cdc445fe0df33c7dd7b7be3e8a16f866 to your computer and use it in GitHub Desktop.
<?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')
);
}
}
<?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