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 SubscribeAsí que, al menos a alto nivel, entendemos que cada recurso tendrá una clave @type
y que esta página -a través de las claves supportedClass
y supportedProperty
- define qué significa ese tipo, qué propiedades tiene y mucha información sobre cada propiedad.
Ahora mismo, sólo tenemos un recurso API, por lo que sólo tenemos una entrada ensupportedClass
, ¿verdad? ¡Pues sorpresa! Hay otra llamada Entrypoint
! Y otra llamada ConstraintViolation
, que define el recurso que se devuelve cuando nuestra API tiene un error de validación.
Hablemos de esta clase Entrypoint
: es una idea bastante bonita. Ya sabemos que cuando vamos a /api
, obtenemos, más o menos, la versión HTML de una "página de inicio" de la API. Pues bien, ¡también hay una versión JSON-LD de esta página! Hay un enlace para verla al final de esta página, pero vamos a llegar a ella de otra manera.
Busca tu terminal: podemos utilizar curl para ver el aspecto de la "página principal" para el formato JSON-LD:
curl -X GET 'https://localhost:8000/api' -H "accept: application/ld+json"
En otras palabras: haz una petición GET a /api
, pero anuncia que quieres que te devuelvan el formato JSON-LD. También enviaré eso a jq
- una utilidad que hace que JSON tenga un aspecto bonito - simplemente sáltate eso si no lo tienes instalado. Y... ¡boom!
¡Saluda a la página de inicio de tu API! Como cada URL representa un recurso único, incluso esta página es un recurso: es... un recurso "Punto de entrada". Tiene los mismos@context
, @id
y @type
, con una "propiedad" real llamada cheeseListing
. Esa propiedad es el IRI del recurso de colección del listado de quesos.
Por cierto, ¡esto se describe en nuestro documento JSON-LD! La clase Entrypoint
tiene una propiedad: cheeseListing
con el tipo hydra:Link
- eso es interesante. Y, es bastante feo, pero la parte rdfs:range
es aparentemente una forma de describir que el recurso al que se refiere esta propiedad es una "colección" que tendrá una propiedadhydra:member
, que será un array donde cada elemento es de tipoCheeseListing
. ¡Woh!
Así que JSON-LD consiste en añadir más contexto a tus datos especificando que nuestros recursos contendrán claves especiales como @context
, @id
y @type
. Sigue siendo JSON normal, pero si un cliente entiende JSON-LD, va a poder obtener mucha más información sobre tu API, de forma automática.
Pero en la Plataforma API, hay otra cosa que vas a ver todo el tiempo, ¡y ya la estamos viendo! La Hidra, que es algo más que un monstruo acuático de muchas cabezas de la mitología griega.
Vuelve a /api/docs.jsonld
. De la misma manera que esto apunta al documento externoxmls
para que podamos referenciar cosas como xmls:integer
, también estamos apuntando a un documento externo llamado hydra
que define más "tipos" o "vocabulario" que podemos utilizar.
Esta es la idea: JSON-LD nos proporcionó el sistema para decir que este dato es de este tipo y este otro tipo. Hydra es una extensión de JSON-LD que añade nuevos vocablos. Dice:
Espera un segundo. JSON-LD es genial y divertido y un excelente invitado a la cena. Pero para que un cliente y un servidor puedan realmente comunicarse, necesitamos más ¡> lenguaje compartido! Necesitamos una forma de definir "clases" dentro de mi API, las propiedades de esas clases y si cada una es legible y escribible. Ah, y también necesitamos también necesitamos poder comunicar las operaciones que admite un recurso: ¿puedo hacer una petición DELETE a este recurso para eliminarlo? ¿Puedo hacer una solicitud PUT para actualizarlo? ¿Qué formato de datos debo esperar de cada operación? ¿Y cuál es la verdadera identidad de Batman?
Hydra tomó el sistema JSON-LD y le añadió una nueva "terminología" -llamada "vocabulario"- que permite definir completamente cada aspecto de tu API.
Llegados a este punto, casi seguro que estás pensando:
Pero espera, esto suena en serio, es exactamente lo mismo que obtuvimos de nuestro documento JSON de OpenAPI.
Y... ¡sí! Si cambiamos la URL a /api/docs.json
, se trata de la especificación OpenAPI. Y si la cambiamos a .jsonld
, de repente tenemos la especificación JSON-LD con Hydra.
Entonces, ¿por qué tenemos ambos? En primer lugar, sí, estos dos documentos hacen básicamente lo mismo: describen tu API en un formato legible por la máquina. El formato JSON-LD e Hydra es un poco más potente que OpenAPI: es capaz de describir algunas cosas que OpenAPI no puede. Pero OpenAPI es más común y tiene más herramientas construidas a su alrededor. Así que, en algunos casos, tener una especificación OpenAPI será útil -como usar Swagger- y otras veces, el documento JSON-LD Hydra será útil. Con la Plataforma API, tienes ambas cosas.
¡Ufff! Bien, ¡basta de teoría! Volvamos a construir y personalizar nuestra API.
Hello,
Don't know why I have this error.
>curl -X GET 'https://127.0.0.1:8000/api' -H "accept: application/ld+json"
curl: (3) URL using bad/illegal format or missing URL
---------------------------------------------------------------------------------------------------------------------------------------------------------------
>php bin/console debug:router
Name Method Scheme Host Path
------------------------------------- -------- -------- ------ -------------------------------------
_twig_error_test ANY ANY ANY /_error/{code}.{_format}
api_entrypoint ANY ANY ANY /api/{index}.{_format}
api_doc ANY ANY ANY /api/docs.{_format}
api_jsonld_context ANY ANY ANY /api/contexts/{shortName}.{_format}
api_cheese_listings_get_collection GET ANY ANY /api/cheese_listings.{_format}
api_cheese_listings_post_collection POST ANY ANY /api/cheese_listings.{_format}
api_cheese_listings_get_item GET ANY ANY /api/cheese_listings/{id}.{_format}
api_cheese_listings_delete_item DELETE ANY ANY /api/cheese_listings/{id}.{_format}
api_cheese_listings_put_item PUT ANY ANY /api/cheese_listings/{id}.{_format}
Can someone do what should I do?
Thank you in advance
Hey zahariastefan462
That's very odd. Try using double quotes instead of single quotes for your host parameter
For Windows users who encountred issues with the curl command, you need to add --ssl-no-revoke at the end
So the full command is :
curl -X GET "https://localhost:8000/api" -H "accept: application/ld+json" --ssl-no-revoke
Love API-Platform, using it as much as possible now.
I also use the Symfony proxy, to make my domains easier to work with (symfony proxy:domain:add my-project, then use https://my-project.wip). Can you suggest how to call fetch with a proxy (https://127.0.0.1:7080 is the default).
I keep thinking there must be a way to define the proxy, like in curl, but I can't find it. For now, I'm simply using localhost and the port, as you do in the tutorial, but then I have to always start the servers in the right order. Is there a way to set the proxy in the fetch call? Or somewhere else?
Hiya Tac-Tacelosky!
Always nice to hear from you :). Beyond what the docs talk about for this - https://symfony.com/doc/cur... - I am not sure, I don't personally use the proxy stuff. I would expect that setting the proxy in your OS and "Re-Applying it" if you're using Chrome (like the docs say) would be enough. Do those docs help at all, or no?
Cheers!
// 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
}
}
Wow, this is AMAZING! 🎉🥳Can't wait to play with it. I had wondered how some of our Java devs had setup Swagger so easily and now I know. Thanks! Great stuff, as per usual!