gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
¡La increÃble documentación interactiva con la que nos hemos topado no es algo de la API Platform! No, en realidad es una biblioteca de documentación de API de código abierto llamada Swagger UI. Y lo realmente genial de Swagger UI es que, si alguien crea un archivo que describa cualquier API, ¡esa API puede obtener todo esto gratis! ¡Me encantan las cosas gratis! Obtenemos Swagger UI porque la API Platform proporciona ese archivo de descripción de forma inmediata. Pero hablaremos de ello más adelante.
Vamos a jugar con esto. Utiliza la ruta POST para crear un nuevo DragonTreasure
. Recientemente hemos saqueado unas "Monedas de oro"... que obtuvimos de "Rico McPato". Está loco. Para nuestros propósitos, ninguno de los otros campos importa realmente. Aquà abajo, pulsa "Ejecutar" y... ¡boom! Cuando te desplaces hacia abajo, podrás ver que se ha realizado una petición POST a /api/dragon_treasures
y se han enviado todos los datos como JSON Entonces, nuestra API devolvió un código de estado "201". Un estado 201 significa que la petición tuvo éxito y se creó un recurso. Luego devolvió este JSON, que incluye un id
de 1
. Asà que, como he dicho, esto no es sólo documentación: ¡realmente tenemos una API que funciona! Aquà también hay algunos campos adicionales: @context
, @id
, y @type
De ellos hablaremos pronto.
Ahora que tenemos un DragonTreasure
con el que trabajar, abre esta ruta "GET", haz clic en "Probar" y luego en "Ejecutar". Me encanta. Swagger acaba de hacer una petición GET
a /api/dragon_treasures
- este ?page=1
es opcional. Nuestra API devolvió información dentro de algo llamado hydra:member
, que aún no es especialmente importante. Lo que importa es que nuestra API devolvió una lista de todos los DragonTreasures
que tenemos actualmente, que es justo éste.
Asà que, en sólo unos minutos de trabajo, tenemos una API completa para nuestra entidad Doctrine. Eso es genial.
Copia la URL de la ruta de la API, abre una nueva pestaña y pégala. ¡Guau! Esto... ¿ha devuelto HTML? Pero hace un segundo, Swagger dijo que hizo una petición GET
a esa URL... y devolvió JSON. ¿Qué está pasando?
Una caracterÃstica de la API Platform se llama "Negociación de contenido". Significa que nuestra API puede devolver el mismo recurso -como DragonTreasure
- en varios formatos, como JSON, o HTML... o incluso cosas como CSV. Un formato ASCII serÃa genial. En cualquier caso, le decimos a la API Platform qué formato queremos pasando una cabecera Accept
en la petición. Cuando utilizamos los documentos interactivos, nos pasa esta cabecera Accept
configurada como application/ld+json
. Pronto hablaremos de la parte ld+json
... pero, gracias a esto, ¡nuestra API devuelve JSON!
Y aunque no lo veamos aquÃ, cuando vas a una página en tu navegador, éste envÃa automáticamente una cabecera Accept
que dice que queremos text/html
. Asà que esto es la API Platform mostrándonos la "representación HTML" de nuestros tesoros dragón..., que no es más que la documentación. Observa: cuando abro la ruta para la que está esta URL, la ejecuta automáticamente.
La cuestión es: si queremos ver la representación JSON de nuestros tesoros dragón, tenemos que pasar esta cabecera Accept
... lo cual es superfácil, por ejemplo, si estás escribiendo JavaScript.
Pero pasar una cabecera personalizada Accept
no es tan fácil en un navegador... y estarÃa bien poder ver la versión JSON de esto. Afortunadamente, la API Platform nos da una forma de hacer trampas. Elimina el ?page=1
para simplificar las cosas. Luego, al final de cualquier ruta, puedes añadir .
seguido de la extensión del formato que quieras: como .jsonld
.
Ahora vemos el recurso DragonTreasure
en ese formato. La API Platform también admite JSON normal de fábrica, asà que podemos ver lo mismo, pero en JSON puro y estándar.
El hecho de que todo esto funcione significa que... aparentemente tenemos una nueva ruta para /api
, asà como un montón de otras rutas nuevas para cada operación -como GET /api/dragon_treasures
. Pero... ¿de dónde vienen? ¿Cómo se añaden dinámicamente a nuestra aplicación?
Para responder a esto, ve a tu terminal y ejecuta:
./bin/console debug:router
Haré esto un poco más pequeño para que podamos verlo todo. ¡SÃ! Cada ruta está representada por una ruta normal, tradicional. ¿Cómo se añaden? Cuando instalamos la API Platform, su receta añadió un archivo config/routes/api_platform.yaml
. Esto es en realidad una importación de rutas. Parece un poco raro, pero activa la API Platform cuando el sistema de rutas se está cargando. A continuación, la API Platform encuentra todos los recursos API de nuestra aplicación y genera una ruta para cada ruta.
La cuestión es que lo único en lo que tenemos que centrarnos es en crear estas bonitas clases PHP y decorarlas con ApiResource
. La API Platform se encarga de todo el trabajo pesado de conectar esas rutas. Por supuesto, tendremos que ajustar la configuración y hablar de cosas más avanzadas, pero ¡eh! Ese es el objetivo de este tutorial. Y ya hemos tenido un comienzo épico.
Lo siguiente: Quiero hablar del secreto que hay detrás de cómo se genera esta documentación Swagger UI. Se llama OpenAPI.
Hey Radu!
Hmm. Do you have a docker-compose.yml
file? If you do and you have Docker running AND you have a container called database
, then when you access the site, the symfony
binary is overriding the DATABASE_URL
env var and setting it to point at that Docker container. If you're setting up your database locally (without Docker), just don't bother starting Docker and delete the docker-compose.yml
file entirely (or at least the matching service).
If my guess is incorrect, let me know!
Cheers!
Hey @weaverryan,
Thanks for the quick reply! You were indeed correct! I've recreated my local container after renaming the database service in the docker-compose.yml file to my_app_database and the issue went away! :)
Cheers,
Radu
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "^3.0", // v3.0.8
"doctrine/annotations": "^1.0", // 1.14.2
"doctrine/doctrine-bundle": "^2.8", // 2.8.0
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
"doctrine/orm": "^2.14", // 2.14.0
"nelmio/cors-bundle": "^2.2", // 2.2.0
"nesbot/carbon": "^2.64", // 2.64.1
"phpdocumentor/reflection-docblock": "^5.3", // 5.3.0
"phpstan/phpdoc-parser": "^1.15", // 1.15.3
"symfony/asset": "6.2.*", // v6.2.0
"symfony/console": "6.2.*", // v6.2.3
"symfony/dotenv": "6.2.*", // v6.2.0
"symfony/expression-language": "6.2.*", // v6.2.2
"symfony/flex": "^2", // v2.2.4
"symfony/framework-bundle": "6.2.*", // v6.2.3
"symfony/property-access": "6.2.*", // v6.2.3
"symfony/property-info": "6.2.*", // v6.2.3
"symfony/runtime": "6.2.*", // v6.2.0
"symfony/security-bundle": "6.2.*", // v6.2.3
"symfony/serializer": "6.2.*", // v6.2.3
"symfony/twig-bundle": "6.2.*", // v6.2.3
"symfony/ux-react": "^2.6", // v2.6.1
"symfony/validator": "6.2.*", // v6.2.3
"symfony/webpack-encore-bundle": "^1.16", // v1.16.0
"symfony/yaml": "6.2.*" // v6.2.2
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
"symfony/debug-bundle": "6.2.*", // v6.2.1
"symfony/maker-bundle": "^1.48", // v1.48.0
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/stopwatch": "6.2.*", // v6.2.0
"symfony/web-profiler-bundle": "6.2.*", // v6.2.4
"zenstruck/foundry": "^1.26" // v1.26.0
}
}
Hi Ryan,
I have an issue. I'm using mysql instead of postgresql (created a docker standard mysql 8 container from mysql:latest).
I was able to create the entity with the maker bundle, the migration, create the database (./bin/console doctrine:database:create) and execute the migration using CLI commands (./bin/console doctrine:migrations:migrate). The database was created and the tables as well.
All steps went successfully until I tried to submit a post request from the https://127.0.0.1:8000/api. I get the following error:
The problem is that for some reason it is trying to query a database named root, when in fact the database that was earlier created is called app.
In my .env file I have:
Any thoughts on this one?
Thanks,
Radu