Filtrar en las relaciones
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.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeVe directamente a /api/users/5.jsonld
. Este usuario posee un CheeseListing
... y hemos decidido incrustar los campos title
y price
en lugar de mostrar sólo el IRI. ¡Genial!
Antes hemos hablado de un filtro muy chulo llamado PropertyFilter
, que nos permite, por ejemplo, añadir ?properties[]=username
a la URL si sólo queremos recuperar ese campo. Lo hemos añadido a CheeseListing
, pero no a User
. ¡Arreglemos eso!
Por encima de User
, añade @ApiFilter(PropertyFilter::class)
. Y recuerda que tenemos que añadir manualmente la declaración use
para las clases de filtro: use PropertyFilter
.
// ... lines 1 - 6 | |
use ApiPlatform\Core\Serializer\Filter\PropertyFilter; | |
// ... lines 8 - 15 | |
/** | |
// ... lines 17 - 20 | |
* @ApiFilter(PropertyFilter::class) | |
// ... lines 22 - 24 | |
*/ | |
class User implements UserInterface | |
// ... lines 27 - 190 |
Y... ¡hemos terminado! Cuando actualizamos, ¡funciona! Aparte de las propiedades JSON-LD estándar, sólo vemos username
.
Selección de propiedades de relación incrustadas
Pero espera, ¡hay más! Quita la parte de ?properties[]=
por un segundo para que podamos ver la respuesta completa. ¿Qué pasaría si quisiéramos obtener sólo la propiedad username
y la propiedad title
de la relación incrustada cheeseListings
? ¿Es posible? Totalmente, sólo tienes que conocer la sintaxis. Vuelve a poner ?properties[]=username
. Ahora añade &properties[
, pero dentro de los corchetes, pon cheeseListings
. Luego[]=
y el nombre de la propiedad: title
. ¡Dale caña! ¡Muy bien! Bueno, el title
está vacío en este CheeseListing
, pero te haces una idea. La cuestión es ésta: PropertyFilter
es una buena idea y puede utilizarse para filtrar datos incrustados sin ningún trabajo adicional.
Buscar en propiedades relacionadas
Hablando de filtros, hemos dado a CheeseListing
un montón de ellos, incluyendo la posibilidad de buscar por title
o description
y filtrar por price
. Vamos a añadir otro.
Desplázate hasta la parte superior de CheeseListing
para encontrar SearchFilter
. Vamos a dividir esto en varias líneas
// ... lines 1 - 16 | |
/** | |
// ... lines 18 - 34 | |
* @ApiFilter(SearchFilter::class, properties={ | |
* "title": "partial", | |
* "description": "partial" | |
* }) | |
// ... lines 39 - 41 | |
*/ | |
class CheeseListing | |
// ... lines 44 - 202 |
Buscar por title
y description
está muy bien. ¿Pero qué pasa si quiero buscar por propietario: encontrar todos los CheeseListings
que pertenecen a un User
concreto? Bueno, ya podemos hacerlo de otra manera: obtener los datos de ese usuario y mirar su propiedad cheeseListings
. Pero tenerlo como filtro podría ser súper útil. Diablos, ¡entonces podríamos buscar todos los listados de quesos propiedad de un usuario concreto y que coincidan con algún título! Y... si los usuarios empiezan a tener muchos cheeseListings
, podríamos decidir no exponer esa propiedad en User
en absoluto: la lista podría ser demasiado larga. La ventaja de un filtro es que podemos obtener todos los listados de quesos de un usuario en una colección paginada.
Para ello... añade owner
ajustado a exact
.
// ... lines 1 - 16 | |
/** | |
// ... lines 18 - 34 | |
* @ApiFilter(SearchFilter::class, properties={ | |
// ... lines 36 - 37 | |
* "owner": "exact" | |
* }) | |
// ... lines 40 - 42 | |
*/ | |
class CheeseListing | |
// ... lines 45 - 203 |
Ve a actualizar los documentos y prueba la ruta GET. Tenemos un nuevo cuadro de filtrado, incluso podemos buscar por varios propietarios. Dentro de la caja, añade el IRI - /api/users/4
. También puedes filtrar por id
, pero se recomienda el IRI.
Ejecuta y... ¡sí! Obtenemos el CheeseListing
para ese User
. Y la sintaxis de la URL es maravillosamente sencilla: ?owner=
y el IRI... que sólo parece feo porque está codificado en la URL.
Buscar listados de quesos por nombre de usuario del propietario
¡Pero podemos volvernos aún más locos! Añade un filtro más: owner.username
ajustado a partial
.
// ... lines 1 - 16 | |
/** | |
// ... lines 18 - 34 | |
* @ApiFilter(SearchFilter::class, properties={ | |
// ... lines 36 - 38 | |
* "owner.username": "partial" | |
* }) | |
// ... lines 41 - 43 | |
*/ | |
class CheeseListing | |
// ... lines 46 - 204 |
Esto es muy bonito. Vuelve a actualizar los documentos y abre la operación de recogida. Aquí está nuestro nuevo cuadro de filtro, para owner.username
. Fíjate en esto: Busca "cabeza" porque tenemos un montón de nombres de usuario con cabeza de queso. ¡Ejecuta! Esto encuentra dos listados de queso propiedad de los usuarios 4 y 5.
Busquemos a todos los usuarios... para estar seguros y... ¡sí! Los usuarios 4 y 5 coinciden con la búsqueda del nombre de usuario. Probemos a buscar exactamente este cheesehead3
. Ponlo en la casilla y... ¡Ejecuta! ¡Ya está! La búsqueda exacta también funciona. Y, aunque estamos filtrando a través de una relación, la URL está bastante limpia:owner.username=cheesehead3
.
Vale, sólo un tema más breve para esta parte de nuestro tutorial: los subrecursos.
Heyyy, thanks a lot for the great courses!
I have a small question regarding 2 things, "Filtering" and "Relations".
I'v been working for quite some time with a framework based on symfony (Shopware), and they have a very powerful searching system. When using the "List" api to get a list of the entitties, we can pass a "Criteria" Json object. Thanks to this "Criteria" object, I can pass any filter on any field I want. I can also inside this object pass "Associations" which basically says, 'Load the fields in this relation object' or 'Just the ID is enough'.
All of this functionality exists even when adding any new entities without any more configurations!
An example of the json object that would be sent with the api is:
Here is another example with "Associations", imagin we are fetching an order, and we want to get all transactions made for this customer, beside the current state of these transactions (Order -> Transaction -> TransactionState):
Do anyone knows how can I implement something like this!! Is there some more config in the background that I can add or some other library.
Thanks a lot in advanced