Buy Access to Course
02.

Nuestro primer ApiRecurso

|

Share this awesome video!

|

Pregunta: ¿has ido alguna vez a la tienda y has comprado accidentalmente demasiado queso? Es la historia de mi vida. O tal vez tengas el problema contrario: ¡estás organizando una gran fiesta y no tienes suficiente queso! Esta es nuestra nueva idea del billón de dólares: una plataforma en la que puedes vender ese trozo extra de Brie que nunca te acabaste o comprar un camión lleno de camembert a alguien que va demasiado excitado al mercado del queso. Sí, es lo que el mundo está pidiendo: un mercado de queso entre iguales. Lo llamamos: Cheese Whiz.

Para el sitio, quizá lo convirtamos en una aplicación de una sola página construida en React o Vue... o quizá sea un poco más tradicional: una mezcla de páginas HTML y JavaScript que haga peticiones AJAX. Y tal vez incluso tengamos una aplicación móvil. En realidad no importa, porque todas estas opciones significan que tenemos que ser capaces de exponer nuestra funcionalidad principal a través de una API.

Generar la entidad

Pero para empezar: olvídate de la API y haz como si este fuera un proyecto Symfony normal y aburrido. El paso 1 es... hmm, probablemente crear algunas entidades de la base de datos.

Abramos nuestro archivo .env y modifiquemos el DATABASE_URL. Mi equipo utilizaroot sin contraseña... y qué tal cheese_whiz para el nombre de la base de datos.

33 lines | .env
// ... lines 1 - 30
DATABASE_URL=mysql://root:@127.0.0.1:3306/cheese_whiz
// ... lines 32 - 33

También puedes crear un archivo .env.local y anular allí DATABASE_URL. Usarroot y sin contraseña es bastante estándar, así que me gusta añadirlo a .env y confirmarlo como predeterminado.

¡Genial! A continuación, en tu terminal, ejecuta

composer require maker:1.11 --dev

para obtener el MakerBundle de Symfony... para que podamos ser perezosos y generar nuestra entidad. Cuando termine, ejecuta

php bin/console make:entity

Llama a la primera entidad: CheeseListing, que representará cada "queso" que esté a la venta en el sitio. Pulsa enter y... ¡oh! te pide:

¿Marcar esta clase como un recurso de la Plataforma API?

MakerBundle pregunta esto porque se ha dado cuenta de que la Plataforma API está instalada. Di "sí". Y antes de añadir ningún campo, ¡vamos a ver qué ha hecho! En mi editor, ¡sí! Esto creó los habituales CheeseListing y CheeseListingRepository. No hay nada especial. Ahora mismo, la única propiedad que tiene la entidad es id. Entonces, ¿qué nos dio la respuesta afirmativa a la pregunta sobre el recurso de la Plataforma API? Esta pequeña anotación de aquí: @ApiResource

111 lines | src/Entity/CheeseListing.php
// ... lines 1 - 7
/**
* @ApiResource()
// ... line 10
*/
class CheeseListing
// ... lines 13 - 111

La verdadera pregunta es: ¿qué activa eso? Lo veremos pronto.

Pero primero, vamos a añadir algunos campos. Veamos, cada listado de quesos probablemente necesite un title, string, 255, no anulable, un description, que será un gran campo de texto, price, que haré un integer -este será el precio en céntimos- por lo que 10 dólares serían 1000, createdAt como datetime y un isPublishedbooleano. Bien: ¡buen comienzo! Pulsa enter para terminar.

¡Enhorabuena! Tenemos una clase CheeseEntity perfectamente aburrida: 7 propiedades con getters y setters

111 lines | src/Entity/CheeseListing.php
// ... lines 1 - 11
class CheeseListing
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\Column(type="text")
*/
private $description;
/**
* @ORM\Column(type="integer")
*/
private $price;
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
/**
* @ORM\Column(type="boolean")
*/
private $isPublished;
// ... lines 45 - 109
}

A continuación, genera la migración con:

php bin/console make:migration

¡Oh! ¡Migraciones no está instalado todavía! No hay problema, sigue la recomendación:

composer require migrations:2.0.0

Pero antes de intentar generarla de nuevo, tengo que asegurarme de que mi base de datos existe:

php bin/console doctrine:database:create

Y ahora ejecuta make:migration:

php bin/console make:migration

Vamos a comprobarlo para asegurarnos de que no hay ninguna sorpresa:

CREATE TABLE cheese_listing...

36 lines | src/Migrations/Version20190508193750.php
// ... lines 1 - 12
final class Version20190508193750 extends AbstractMigration
{
// ... lines 15 - 19
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('CREATE TABLE cheese_listing (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, description LONGTEXT NOT NULL, price INT NOT NULL, created_at DATETIME NOT NULL, is_published TINYINT(1) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
}
// ... lines 27 - 34
}

¡Sí! ¡Tiene buena pinta! Cierra eso y ejecuta:

php bin/console doctrine:migrations:migrate

¡Saluda a tu API!

¡Genial! Llegados a este punto, tenemos una entidad Doctrine completamente tradicional, excepto por ésta, la anotación @ApiResource(). Pero esto lo cambia todo. Esto le dice a la Plataforma API que quieres exponer esta clase como una API.

Compruébalo: actualiza la página /api. ¡Vaya! ¡De repente esto dice que tenemos cinco nuevas rutas, u "operaciones"! Una operación GET para recuperar una colección de CheeseListings, una operación POST para crear una nueva, GET para recuperar una solaCheeseListing, DELETE para... ya sabes... borrar y PUT para actualizar una CheeseListing existente. ¡Eso es un CRUD completo, basado en la API!

Y esto no es sólo documentación: estas nuevas rutas ya funcionan. Vamos a comprobarlos a continuación, a saludar a algo llamado JSON-LD y a aprender un poco sobre cómo funciona esta magia entre bastidores.