Skip to content

Commit

Permalink
Practice #6: filter, sort and pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
clementvtrd committed Dec 9, 2022
1 parent 1367c93 commit 49a5743
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 11 deletions.
50 changes: 45 additions & 5 deletions src/Controller/API/Dinosaurs/GetAll.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,61 @@
namespace App\Controller\API\Dinosaurs;

use App\Entity\Dinosaur;
use App\Repository\DinosaurRepository;
use Doctrine\Persistence\ManagerRegistry;
use Nelmio\ApiDocBundle\Annotation\Model;
use OpenApi\Attributes as OA;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\SerializerInterface;

class GetAll extends AbstractController
{
public function __construct(
private readonly SerializerInterface $serializer
private readonly SerializerInterface $serializer,
private readonly DinosaurRepository $dinosaurs
)
{
}

#[Route('/api/dinosaurs', methods: 'GET')]
#[OA\Tag('dinosaur')]
#[OA\Parameter(
parameter: 'page',
name: 'page',
schema: new OA\Schema(
type: 'integer',
default: 0,
minimum: 0
)
)]
#[OA\Parameter(
parameter: 'limit',
name: 'limit',
in: 'query',
schema: new OA\Schema(
type: 'integer',
default: 25,
minimum: 1
),
)]
#[OA\Parameter(
parameter: 'filters',
name: 'filters',
in: 'query',
schema: new OA\Schema(type: 'object'),
example: '{"gender": "Male"}'
)]
#[OA\Parameter(
parameter: 'sorts',
name: 'sorts',
in: 'query',
schema: new OA\Schema(type: 'object'),
example: '{"age": "ASC"}'
)]
#[OA\Response(
response: Response::HTTP_OK,
description: 'List all the dinosaurs',
Expand All @@ -37,11 +73,15 @@ public function __construct(
)
)
)]
public function __invoke(ManagerRegistry $manager): Response
public function __invoke(Request $request): Response
{
$dinosaurs = $manager
->getRepository(Dinosaur::class)
->findAll()
$dinosaurs = $this->dinosaurs
->search(
filters: json_decode($request->query->get('filters')),
sorts: json_decode($request->query->get('sorts')),
page: $request->query->get('page'),
limit: $request->query->get('limit')
)
;

$content = $this->serializer->serialize(
Expand Down
63 changes: 57 additions & 6 deletions src/Repository/DinosaurRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,77 @@

use App\Entity\Dinosaur;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;

class DinosaurRepository extends ServiceEntityRepository
{
private const alias = 'dinosaur';

public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Dinosaur::class);
}

public function search(?string $q): array
/**
* @param array<string, string> $filter
* @param array<string, 'DESC'|'ASC'> $sorts
*/
public function search(
?string $q = null,
?array $filters = null,
?array $sorts = null,
?int $page = 0,
?int $limit = 25
): array
{
if ($q === null) {
return $this->findAll();
$queryBuilder = $this->createQueryBuilder(self::alias);

if (null === $q) {
$queryBuilder
->where(sprintf('%s.name = :q', self::alias))
->setParameter('q', $q)
;
}

if (null !== $filters) {
$queryBuilder = $this->filter($queryBuilder, $filters);
}

return $this->createQueryBuilder('d')
->where('d.name = :q')
->setParameter('q', $q)
if (null !== $sorts) {
$queryBuilder = $this->sort($queryBuilder, $sorts);
}

return $queryBuilder
->getQuery()
->setFirstResult($page * $limit)
->setMaxResults($limit)
->getResult()
;
}

/**
* @param array<string, string> $filters
*/
private function filter(QueryBuilder $queryBuilder, array $filters): QueryBuilder
{
foreach ($filters as $property => $value) {
$queryBuilder
->andWhere(sprintf('%s.%s = %s', self::alias, $property, $value))
;
}

return $queryBuilder;
}

private function sort(QueryBuilder $queryBuilder, array $sorts): QueryBuilder
{
foreach ($sorts as $property => $direction) {
$queryBuilder
->addOrderBy(sprintf('%s.%s', self::alias, $property), $direction)
;
}

return $queryBuilder;
}
}

0 comments on commit 49a5743

Please sign in to comment.