Symfony paso a paso (4) – Migraciones y fixtures

Hasta ahora nuestra apilcación ni persiste ni lee ningún tipo de información en la base de datos. Para conseguir esto utilizaremos Doctrine (el ORM instegrado en Symfony), quien se encargará de mapear nuestras entidades a tablas de la base de datos MySql.

Migraciones en Symfony

Para gestoinar las modificaciones en la base de datos voy a utilizar migraciones. Las migraciones se encargarán de crear las tablas, añadir nuevas columnas, eliminar otras … en resumen: realizaran todas las modificaciones en la estructura de de la base de datos, por lo que no tendremos que preocuparnos de modificar manualmente la base de datos de producción cada vez que hacemos algun cambio en las entidades.

Para utilizar migraciones con symfony voy a utilizar el búndle «doctrine-migrations-bundle» asi que se lo pedimos a composer:

composer require doctrine/doctrine-migrations-bundle "^1.0"

Siguiendo la documentación de la página del bundle lo registramos en nuestro kernel (yo utilizaré la configuracion por defecto) y con esto ya tendríamos disponibles las migraciones.

Mapeando la entidad Word

En el post anterior habíamos creado nuestra entidad «Word», vamos a ahora a crear una migración que se encargará de crear el sql necesario para mapear la entidad Word a la base de datos. Esto es: creará la tabla «word» con las columnas necesarias para almacenar sus propiedades.

Con el bundle ya instalado y registrado, vermos que tenemos nuevos comandos en nuestra consola. En concreto el que nos interesa ahora mismo es que generará nuestro archivo de migración:

bin/console doctrine:migrations:diff

Como resultado de este comando veremos un nuevo archivo an «app/DoctrineMigrations/». Si abrimos este archivo para ver su contenido veremos que contiene dos métodos:

  • up() que contiene el sql necesario para crear la tabla de nuestra entidad Word
  • down() que contiene el SQL necesario para eliminar la BD en caso de querer hacer un downgrade

Ya tenemos nuestro archivo de migración!. Si necesitasemos hacer algo más complejo con las base de datos este sería el fichero que tendríamos que modificar. Podríamos por ejemplo añadir código para crear otra tabla que necesitásemos, modificar alguna otra, etc.

Por último nos faltaría ejecutar nuestra migración. Ejecutar una migración significa aplicar esos cambios especificados en el archivo de migraciones sobre la base de datos.

Ejecutando migraciones en Symfony

Para ejecutar las migraciónes tenemos el comando:

bin/console doctrine:migrations:migrate

Si todo ha ido bien deberíamos ver dos nuevas tablas en la BD:

  • word – La tabla de nuestra entidad word
  • migation_versions – Esta tabla la crea el bundle doctrine-migrations-bundle para llevar la cuenta de las migraciones que se han ejecutado y saber cuando aplicar o no nuevas migraciones.

El comando anterior ejecutará todas las migraciones que encuentre que no estén registradas en la tabla migration_versions, y las ejecutará en el orden adecuado. Por lo que con este comando podemos recrear completamente la estructura de la base de datos en cualquier momento.

Es importante entender que las migraciones se refieresn a la estructura de la base de datos, y no a los datos contenidos en ella. Para rellenar la tabla con datos en el entorno de producción tenemos otra técnica que nos ayudará a tener un conjunto de datos «conocido» lo que nos facilitará mucho la tarea a la hora de desarrollar y testear nuevas funcionalidades. Estos datos son las «fixtures».

Antes de nada vamos a commitear nuestros avances para seguir toqueteando sin miendo a romper nada:

git add .
git commit -m  "First migration. Ads Word entity"

Fixtures – Añadiendo datos a nuestra tabla en el entorno de desarrollo

En este punto ya podríamos añadir datos a la tabla «word» de forma manual, ya séa conectandonos al servidor de mysql o mediante algun cliente gráfico (phpMyAdmin, MysqlWorkbench, …) pero hay una forma mejor de hacerlo, y es mediante fixtures.

Las fixtures son un mecanismo para rellenar nuestras bases de datos en el entorno de desarrollo con un conjuto de datos conocido. Utilizar fixtures tiene muchas ventajas y aun que hay que «invertir» inicialmente algo de tiempo en crearlas, a la larga se ahorra muchísimo tiempo al no tener que introducir datos de forma manual cada vez que queremos probar algo.

Mezclando migraciones y fixtures podemos resetear la bd completa a un estado conocido en cualquier momento,con lo que:

  • Si necesitamos mover el proyecto a otro pc, carpeta, o eviarselo a alguien, bastea ejecutaruno o dos comandos para tener funcionando la bd
  • A medida que le dedicas mas tiempo a un proyecto, acabas memorizando tus fixtures lo que te hace mas sencillo comprobar que los datos se comprtan como esperas
  • Permite hacer test automatizados con resultados deterministas, lo que a mi parecer los hace más fiables
  • Te obliga desde un principio a pensar en las propiedades y relaciones de tus entidades, y posiblemente te obligue a replantear alguna de ellas en una faste temprana del desarrollo, lo que te puede evitar horas de refactorizacion.

 

Vamos al lío: para manejar las fixtures voy a utilizar http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html

Pedimos a composer que instale el bundle

composer require --dev doctrine/doctrine-fixtures-bundle

Y lo registramos en el kernel siguiendo la documentación del bundle. Esta vez tendremos cuidado de registrar el bundle solo en los entornos de desarrollo y testing tal como dice la documentación.

Ahora creamos nuestro archivo de fixtures para la entidad «Word». La propia documentación nos dice que debemos crear las fixtures en el directorio «DataFixtures\ORM» .

Yo a mi archivo de fixtures para la entidad Word le voy a llamar «WordFixture». Este archivo se encargará de crear 10 «words» y persistirlas en la BD.

namespace WWBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use WWBundle\Entity\Word;

class WordFixture implements FixtureInterface
{
    public function load(ObjectManager $manager)
    {
        for ($i=0; $i<10; $i++){ 
		$word = new Word(); 
		$word->setName('palabra_' . ($i+1));
		$word->setDescription('Descripción de la palabra_' . ($i+1));
		$manager->persist($word);
        }
        $manager->flush();
    }
}

Para ejecutar la carga de estas fixtures tenemos el comando:

bin/console doctrine:fixtures:load

Y ya lo tenemos, si exploramos nuestra tabla vermos que se han creado 10 nuevas filas con los datos que le ha dicho nuestra fixture.

Esto se merece un commit

git add .
git commit -m  "First fixture. Ads Word fixture"

 

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *