raw query migrations php git entity-framework symfony doctrine2

php - query - Migraciones de Doctrine: ¿Cómo evitar errores de SQL en el paso postUp?



doctrine native query (1)

¿Cómo maneja las migraciones al implementar aplicaciones Symfony2 que usan Doctrine ORM?

He estado usando DoctrineMigrationsBundle. Funciona bien si evita tratar de usar entidades en la parte postUp () de la migración. Sin embargo, si lo haces, te metes en problemas.

Aquí hay un pseudocódigo para explicar el problema:

/* Migration1.php */ class Migration1 extends... implements ContainerAwareInterface { public function up(...) { query("CREATE TABLE entities WITH COLUMNS col1, col2;"); } public function postUp(...) { $e = new Entity(); $e->setCol1("value1"); $e->setCol2("value2"); $entityManager->persist($e); } } /* Migration2.php */ class Migration2 extends... implements ContainerAwareInterface { public function up(...) { query("ALTER TABLE entities ADD col3"); } }

Caso práctico 1:

  • Los desarrolladores cambian el código de la aplicación y preparan Migration1
  • El código se implementa en el servidor, incluida la ejecución de las migraciones
  • Los desarrolladores cambian el código de la aplicación y preparan Migration2
  • El código se implementa en el servidor, incluida la ejecución de las migraciones

Todo funciona bien.

Caso práctico 2:

  • Los desarrolladores cambian el código de la aplicación y preparan Migration1
  • Los desarrolladores cambian el código de la aplicación y preparan Migration2
  • El código se implementa en el servidor, incluida la ejecución de las migraciones

Esto no funciona. ¿Por qué?

El código en la parte postUp () de Migration1 se ejecutará con el código de aplicación más nuevo. Esto significa que Doctrine ORM esperará que col3 ya esté presente en la tabla de entidades. Sin embargo, dado que Migration2 no se ejecutó aún hasta ese momento, no hay campo col3. Intentar persistir una nueva entidad en Migration1 produce un error de SQL.

He encontrado dos ideas para solucionar este problema:

  • Al implementar un nuevo código, use el sistema de control de versiones. Verifique cada confirmación por separado, ejecute las migraciones en cada confirmación hasta que llegue al nuevo compromiso O
  • No use postUp () para cambiar las entidades. Trate con entidades en scripts separados una vez que se hayan realizado todos los cambios estructurales en la base de datos.

Comente con su experiencia sobre el tema y explique cómo lidia con él. Estoy seguro de que algunos de ustedes se han encontrado con esto en la práctica.


El escenario que describe perfectamente muestra que no es posible (en general) usar entidades en Migraciones de Doctrina.

Así que me temo que la única manera de hacer que esto funcione de manera robusta es descender al nivel DBAL:

public function postUp(...) { $this->connection->insert(''entities'', [ ''col1'' => ''value1'', ''col2'' => ''value2'' ]); }

Al utilizar la consulta DBAL, las columnas que se utilizarán se suministran directamente en lugar de indirectamente a través de la entidad definida por el código de la aplicación, que no necesita estar sincronizada con la estructura de la tabla actual.

Consulte también la sección 4.2 de la publicación "Cómo trabajar con migraciones de Doctrine en Symfony" , que también describe este problema con el uso de entidades en Migraciones de Doctrina, especialmente la siguiente cita:

no use entidades dentro de las migraciones, no debe confiar en el código de entidad (PHP), ¡sino solo en la base de datos!