Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Paginación

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Si tenemos un millón, o mil... o incluso cien listados de quesos, no podemos devolverlos todos cuando alguien hace una petición GET a /api/cheeses! La forma de resolverlo en una API es realmente la misma que en la web: ¡la paginación! Y en la Plataforma API... ah, es tan aburrido... obtienes un sistema de paginación potente y flexible... sin hacer... nada.

Vayamos a la operación POST y creemos unos cuantos listados más de queso. Pondré algunos datos sencillos... y ejecutaré un montón de veces... en avance rápido. En un proyecto real, utilizaría accesorios de datos para ayudarme a obtener datos ficticios útiles.

Deberíamos tener unos 10 más o menos gracias a los 4 con los que empezamos. Ahora, dirígete a la operación de recogida GET... y pulsa Ejecutar. Seguimos viendo todos los resultados, porque la Plataforma API muestra 30 resultados por página, por defecto. Como no me apetece añadir 20 más manualmente, ¡este es un buen momento para aprender a cambiarlo!

Controlar los elementos por página

En primer lugar, esto se puede cambiar globalmente en tu archivo config/packages/api_platform.yaml. No lo mostraré ahora, pero recuerda siempre que puedes ejecutar

php bin/console debug:config api_platform

para ver una lista de toda la configuración válida para ese archivo y sus valores actuales. Eso revelaría una sección de collection.pagination que está llena de configuraciones.

Pero también podemos controlar el número de elementos por página en función de cada recurso. Dentro de la anotación @ApiResource, añade attributes={}... que es una clave que contiene una variedad de configuración aleatoria para la Plataforma API. Y luego,"pagination_items_per_page": 10.

... lines 1 - 15
/**
* @ApiResource(
... lines 18 - 25
* attributes={
* "pagination_items_per_page"=10
* }
* )
... lines 30 - 34
*/
class CheeseListing
... lines 37 - 167

He mencionado antes que gran parte de la Plataforma API consiste en aprender exactamente qué puedes configurar dentro de esta anotación y cómo. Este es un ejemplo perfecto.

Vuelve a la documentación, no hace falta que la actualices. Simplemente pulsa Ejecutar. Veamos... el total de ítems es de 11... ¡pero si lo cuentas, sólo muestra 10 resultados! Hola paginación! También tenemos una nueva propiedad hydra:view. Ésta anuncia que se está produciendo la paginación y que podemos "navegar" a través de las otras páginas: podemos seguirhydra:first, hydra:last y hydra:next para ir a la primera, a la última o a la siguiente página. Las URLs son exactamente como yo quiero: ?page=1, ?page=2 y así sucesivamente.

Abre una nueva pestaña y vuelve a /api/cheeses.jsonld. Sí, los 10 primeros resultados. Ahora añade ?page=2... para ver el único y último resultado.

El filtrado también sigue funcionando. Prueba con .jsonld?title=cheese. Eso devuelve... sólo 10 resultados... ¡así que no hay paginación! Eso no es divertido. Volvamos a los documentos, abramos la ruta POST y añadamos algunas más. Pero asegurémonos de añadir uno con "queso" en el título. Pulsa Ejecutar unas cuantas veces.

Ahora ve a refrescar la operación de recogida GET con ?title=cheese. ¡Qué bien! Tenemos 13 resultados en total y esto muestra los 10 primeros. ¡Lo que está muy bien es que los enlaces de paginación incluyen el filtro! Esto es súper útil en JavaScript: no tienes que intentar piratear la URL manualmente combinando la información de pagey del filtro: basta con leer los enlaces de hydra y utilizarlos.

A continuación, sabemos que nuestra API puede devolver JSON-LD, JSON y HTML. Y... eso es probablemente todo lo que necesitamos, ¿verdad? Veamos lo fácil que es añadir más formatos... incluso hacer que nuestros listados de quesos se puedan descargar como CSV.

Leave a comment!

2
Login or Register to join the conversation
Eric Avatar
Eric Avatar Eric | posted hace 4 años | edited

In order for a client application, that is consuming a Hydra formatted JSON response, to know what the last page number is they would need to parse the "page" query parameter off the "hydra:last" string, correct?

Example: using this format it would be very easy to have pagination links to the next and previous pages. But if a client application wanted to show more page numbers available (ie: linking to pages 1, 2, 3 .... 5, and 6) they would need to parse the "page" query parameter, determine that the last page is 6 and build the links from there, correct?

Just making sure this is suggested approach as I've always passed something like the "lastPage": 6 in a JSON response containing paginated results.

Thanks!

Reply

Hey Eric

I think your approach is correct. You will have to read the last key value and build your pagination table dynamically

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

Este tutorial funciona muy bien para Symfony 5 y la Plataforma API 2.5/2.6.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "api-platform/core": "^2.1", // v2.4.3
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "doctrine/annotations": "^1.0", // 1.10.2
        "doctrine/doctrine-bundle": "^1.6", // 1.11.2
        "doctrine/doctrine-migrations-bundle": "^2.0", // v2.0.0
        "doctrine/orm": "^2.4.5", // v2.7.2
        "nelmio/cors-bundle": "^1.5", // 1.5.5
        "nesbot/carbon": "^2.17", // 2.19.2
        "phpdocumentor/reflection-docblock": "^3.0 || ^4.0", // 4.3.1
        "symfony/asset": "4.2.*|4.3.*|4.4.*", // v4.3.11
        "symfony/console": "4.2.*", // v4.2.12
        "symfony/dotenv": "4.2.*", // v4.2.12
        "symfony/expression-language": "4.2.*|4.3.*|4.4.*", // v4.3.11
        "symfony/flex": "^1.1", // v1.17.6
        "symfony/framework-bundle": "4.2.*", // v4.2.12
        "symfony/security-bundle": "4.2.*|4.3.*", // v4.3.3
        "symfony/twig-bundle": "4.2.*|4.3.*", // v4.2.12
        "symfony/validator": "4.2.*|4.3.*", // v4.3.11
        "symfony/yaml": "4.2.*" // v4.2.12
    },
    "require-dev": {
        "symfony/maker-bundle": "^1.11", // v1.11.6
        "symfony/stopwatch": "4.2.*|4.3.*", // v4.2.9
        "symfony/web-profiler-bundle": "4.2.*|4.3.*" // v4.2.9
    }
}
userVoice