Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Subrecursos

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

En algún momento, un cliente de la API... que podría ser nuestro JavaScript, probablemente querrá obtener una lista de todos los cheeseListings de un User específico. Y... ya podemos hacerlo de dos maneras diferentes: buscar un propietario específico aquí a través de nuestro filtro... o recuperar el User específico y mirar su propiedad cheeseListings.

Si lo piensas, un CheeseListing es casi como un recurso "hijo" de un User: los listados de queso pertenecen a los usuarios. Y por esa razón, a algunas personas les gustaría poder obtener los listados de queso de un usuario yendo a una URL como ésta: /api/users/4/cheeses... o algo similar.

Pero... eso no funciona. Esta idea se llama "subrecursos". Ahora mismo, cada recurso tiene su propia, especie de, URL base: /api/cheeses y /api/users. Pero es posible, más o menos, "mover" los quesos bajo los usuarios.

He aquí cómo: en User, busca la propiedad $cheeseListings y añade @ApiSubresource.

... lines 1 - 6
use ApiPlatform\Core\Annotation\ApiSubresource;
... lines 8 - 26
class User implements UserInterface
{
... lines 29 - 62
/**
... lines 64 - 66
* @ApiSubresource()
*/
private $cheeseListings;
... lines 70 - 190
}

¡Vamos a refrescar los documentos! ¡Woh! Tenemos una nueva ruta!/api/users/{id}/cheese_listings. Aparece en dos sitios... porque está algo relacionado con los usuarios... y algo relacionado con los listados de queso. La URL es cheese_listings por defecto, pero se puede personalizar.

Así que... ¡probemos! Cambia la URL a /cheese_listings. Ah, y añade el.jsonld al final. ¡Ya está! El recurso de la colección de todos los quesos que pertenecen a este User.

¡Los sub-recursos son bastante chulos! Pero... también son un poco innecesarios: ya hemos añadido una forma de obtener la colección de listados de quesos de un usuario a través de SearchFilteren CheeseListing. Y el uso de subrecursos significa que tienes más rutas que controlar y, cuando llegamos a la seguridad, más rutas significan más control de acceso en el que pensar.

Así que, utiliza subrecursos si quieres, pero no recomiendo añadirlos en todas partes, ya que hay un coste por la complejidad añadida. Ah, y por cierto, hay un montón de cosas que puedes personalizar en los subrecursos, como los grupos de normalización, la URL, etc. Está todo en los documentos y es bastante similar a los tipos de personalización que hemos visto hasta ahora.

En el caso de nuestra aplicación, voy a eliminar el subrecurso para simplificar las cosas.

Y... ¡hemos terminado! Bueno, hay muchas más cosas interesantes que cubrir - ¡incluyendo la seguridad! Ese es el tema del próximo tutorial de esta serie. Pero ¡déjate llevar por el salto y choca los cinco! ¡Ya hemos desbloqueado una gran cantidad de poder! Podemos exponer entidades como recursos de la API, personalizar las operaciones, tomar el control total del serializador de un montón de maneras diferentes y un montón más. Así que empieza a construir tu preciosa nueva API, cuéntanoslo y, como siempre, si tienes preguntas, puedes encontrarnos en la sección de comentarios.

Muy bien amigos, ¡hasta la próxima!

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