Skip to content

Examples for custom controllers #638

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 5, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions core/pagination.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,128 @@ class Book
```

Please note that this parameter will always be forced to false when the resource have composite keys due to a [bug in doctrine](https://github.com/doctrine/doctrine2/issues/2910)

## Custom Controller Action

In case you're using a custom controller action make sure you return the `Paginator` object to get the full hydra response with `hydra:view` (which contains information about first, last, next and previous page). The following examples show how to handle it within a repository method. The controller needs to pass through the page number. You will need to use the Doctrine Paginator and pass it to the API Platform Paginator.

First example:

```php
<?php

//src/Repository/BookRepository.php

namespace App\Repository;

use App\Entity\Book;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator;
use Doctrine\Common\Collections\Criteria;

class BookRepository extends ServiceEntityRepository
{
const ITEMS_PER_PAGE = 20;

private $tokenStorage;

public function __construct(
RegistryInterface $registry,
TokenStorageInterface $tokenStorage
) {
$this->tokenStorage = $tokenStorage;
parent::__construct($registry, Book::class);
}

public function getBooksByFavoriteAuthor(int $page = 1): Paginator
{
$firstResult = ($page -1) * self::ITEMS_PER_PAGE;

$user = $this->tokenStorage->getToken()->getUser();
$queryBuilder = $this->createQueryBuilder();
$queryBuilder->select('b')
->from(Book::class, 'b')
->where('b.author = :author')
->setParameter('author', $user->getFavoriteAuthor()->getId())
->andWhere('b.publicatedOn IS NOT NULL');

$criteria = Criteria::create()
->setFirstResult($firstResult)
->setMaxResults(self::ITEMS_PER_PAGE);
$queryBuilder->addCriteria($criteria);

$doctrinePaginator = new DoctrinePaginator($queryBuilder);
$paginator = new Paginator($doctrinePaginator);

return $paginator;
}
}
```
The Controller would look like this:

```php
<?php

// src/Controller/Book/GetBooksByFavoriteAuthorAction.php

namespace App\Controller\Book;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator;
use App\Service\Book\BookService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;

class GetBooksByFavoriteAuthorAction extends AbstractController
{
public function __invoke(Request $request, BookService $bookService): Paginator
{
$page = (int) $request->query->get('page', 1);

return $bookService->getBooksByFavoriteAuthor($page);
}
}
```

The service need to use the proper repository method.
You can also use the Query object inside the repository method and pass it to the Paginator instead of passing the QueryBuilder and using Criteria. Second Example:

```php
<?php

//src/Repository/BookRepository.php

namespace App\Repository;

// use...

class BookRepository extends ServiceEntityRepository
{
// constant, variables and constructor...

public function getBooksByFavoriteAuthor(int $page = 1): Paginator
{
$firstResult = ($page -1) * self::ITEMS_PER_PAGE;

$user = $this->tokenStorage->getToken()->getUser();
$queryBuilder = $this->createQueryBuilder();
$queryBuilder->select('b')
->from(Book::class, 'b')
->where('b.author = :author')
->setParameter('author', $user->getFavoriteAuthor()->getId())
->andWhere('b.publicatedOn IS NOT NULL');

$query = $queryBuilder->getQuery()
->setFirstResult($firstResult)
->setMaxResults(self::ITEMS_PER_PAGE);

$doctrinePaginator = new DoctrinePaginator($query);
$paginator = new Paginator($doctrinePaginator);

return $paginator;
}
}
```