gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
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.
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.
... 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
... 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 isPublished
booleano. Bien: ¡buen comienzo! Pulsa enter para terminar.
¡Enhorabuena! Tenemos una clase CheeseEntity
perfectamente aburrida: 7 propiedades con getters y setters
... 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...
... 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
¡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.
// 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
}
}