Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Operaciones

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

Pongamos manos a la obra para personalizar nuestra API. Una API RESTful se basa en recursos. Tenemos un recurso -nuestro CheeseListing - y, por defecto, la Plataforma API ha generado 5 rutas para él. Estos se llaman "operaciones".

Operaciones de colección y de elementos

Las operaciones se dividen en dos categorías. En primer lugar, las operaciones de "colección". Son las URL que no incluyen {id} y en las que el "recurso" sobre el que operas es técnicamente la "colección de listados de quesos". Por ejemplo, estás "obteniendo" la colección o estás "añadiendo" a la colección con POST.

Y en segundo lugar, las operaciones de "artículos". Estas son las URL que sí tienen la parte {id}, cuando estás "operando" sobre un único recurso de listado de quesos.

Lo primero que podemos personalizar es qué operaciones queremos realmente Por encima deCheeseListing, dentro de la anotación, añade collectionOperations={} con"get" y "post" dentro. Luego itemOperations con {"get", "put", "delete"}.

Tip

A partir de ApiPlatform 2.5, también hay una operación patch. Funciona como la operación put y se recomienda sobre put cuando sólo quieres cambiar algunos campos (que es la mayoría de las veces). Para permitir la operación patch, añade esta configuración:` // config/packages/api_platform.yaml api_platform:

patch_formats:
    json: ['application/merge-patch+json']

... lines 1 - 7
/**
* @ApiResource(
* collectionOperations={"get", "post"},
* itemOperations={"get", "put", "delete"}
* )
... line 13
*/
class CheeseListing
... lines 16 - 116

Gran parte del dominio de la Plataforma API se reduce a aprender qué opciones puedes pasar dentro de esta anotación. Esta es básicamente la configuración por defecto: queremos las cinco operaciones. Así que no es de extrañar que, cuando actualizamos, no veamos ningún cambio. Pero, ¿qué pasa si no queremos permitir a los usuarios eliminar un listado de quesos? Tal vez, en lugar de eso, en el futuro, añadamos una forma de "archivar" los mismos. Eliminar "delete".

... lines 1 - 7
/**
* @ApiResource(
... line 10
* itemOperations={"get", "put"}
* )
... line 13
*/
... lines 15 - 116

En cuanto hagamos eso... ¡boom! Desaparece de nuestra documentación. Sencillo, ¿verdad? ¡Sí! Pero acaban de ocurrir un montón de cosas geniales. Recuerda que, entre bastidores, la interfaz de usuario de Swagger se construye a partir de un documento de especificaciones de la API abierta, que puedes ver en /api/docs.json. La razón por la que el punto final "eliminar" desapareció de Swagger es que desapareció de aquí. La Plataforma API mantiene actualizado nuestro documento de "especificaciones". Si miraras el documento de especificaciones JSON-LD, verías lo mismo.

Y, por supuesto, también ha eliminado por completo la ruta -puedes comprobarlo ejecutando:

php bin/console debug:router

Sí, sólo GET, POST, GET y PUT.

Personalizar la URL del recurso (shortName)

Hmm, ahora que lo veo, no me gusta la parte cheese_listings de las URLs... La Plataforma API la genera a partir del nombre de la clase. Y realmente, en una API, no deberías obsesionarte con el aspecto de tus URLs, no es importante, especialmente -como verás- cuando tus respuestas a la API incluyen enlaces a otros recursos. Pero... podemos controlar esto.

Vuelve a dar la vuelta y añade otra opción: shortName ajustada a cheeses.

... lines 1 - 7
/**
* @ApiResource(
... lines 10 - 11
* shortName="cheeses"
... lines 13 - 14
*/
... lines 16 - 117

Ahora ejecuta de nuevo debug:router:

php bin/console debug:router

¡Eh! /api/cheeses! ¡Mucho mejor! Y ahora vemos lo mismo en nuestros documentos de la API.

Personalizar los detalles de la ruta de la operación

Vale: así podemos controlar qué operaciones queremos en un recurso. Y más adelante aprenderemos a añadir operaciones personalizadas. Pero también podemos controlar bastante sobre las operaciones individuales.

Sabemos que cada operación genera una ruta, y la Plataforma API te da un control total sobre el aspecto de esa ruta. Compruébalo: divide itemOperations en varias líneas. Entonces, en lugar de decir simplemente "get", podemos decir "get"={} y pasar esta configuración extra.

Prueba a poner "path"= en, no sé, "/i❤️️cheeses/{id}".

... lines 1 - 7
/**
* @ApiResource(
... line 10
* itemOperations={
* "get"={"path"="/i❤️cheeses/{id}"},
* "put"
* },
... line 15
* )
... line 17
*/
... lines 19 - 120

Ve a ver los documentos ¡Ja! ¡Eso funciona! ¿Qué más puedes poner aquí? Para empezar, cualquier cosa que se pueda definir en una ruta, se puede añadir aquí - comomethod, hosts, etc.

¿Qué más? Bueno, a lo largo del camino, aprenderemos sobre otras cosas específicas de la plataforma API que puedes poner aquí, como access_control para la seguridad y formas de controlar el proceso de serialización.

De hecho, ¡vamos a aprender sobre ese proceso ahora mismo! ¿Cómo transforma la Plataforma API nuestro objeto CheeseListing -con todas estas propiedades privadas- en el JSON que hemos estado viendo? Y cuando creamos un nuevo CheeseListing, ¿cómo convierte nuestro JSON de entrada en un objeto CheeseListing?

Entender el proceso de serialización puede ser la pieza más importante para desbloquear la Plataforma API.

Leave a comment!

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
    }
}