Skip to main content

Migraciones

¿Qué hace internamente?

El comando:

Obtiene el SchemaManager de Doctrine

Ejecuta cada método createXTable()

Verifica si la tabla existe

La crea solo si no existe

$schemaManager = $this->connection->createSchemaManager();

📋 Tablas que se crean 1️⃣ Tabla anidada

Define la configuración de tablas anidadas / subgrillas.

Uso típico:

CRUDs con relaciones padre → hijo

Configuración visual y funcional de subtablas

Campos clave:

nivel_db

tabla_db

consulta_crear_tabla

activate_nested_table_db

2️⃣ Tabla menu

Define los menús principales del sistema.

Campos importantes:

nombre_menu

url_menu

icono_menu

orden_menu

3️⃣ Tabla submenu

Define los submenús asociados a un menú.

Relación lógica:

submenu.id_menu → menu.id_menu

Campos clave:

nombre_submenu

url_submenu

orden_submenu

4️⃣ Tabla usuario

Tabla principal de usuarios del sistema.

Incluye:

Autenticación

Roles

Avatares

Tokens

Índices importantes:

email (único)

usuario (único)

5️⃣ Tabla usuario_menu

Controla qué menús ve cada usuario.

Campos:

id_usuario

id_menu

visibilidad_menu

Usada para:

Permisos

Menús dinámicos

6️⃣ Tabla usuario_submenu

Controla submenús visibles por usuario.

Permite:

Seguridad granular

Ocultar subopciones

7️⃣ Tabla modulos

⚠️ Tabla central del framework

Define completamente el comportamiento de cada CRUD.

Incluye configuración para:

Queries

Formularios

Grillas

Filtros

Búsqueda

Recaptcha

PDFs

Callbacks

Relaciones (INNER / LEFT JOIN)

👉 Esta tabla permite un CRUD declarativo sin código.

🔒 Seguridad del sistema

Las migraciones no borran datos

No alteran tablas existentes

Evitan colisiones por nombres duplicados

🛠️ Cómo crear nuevas tablas (migraciones personalizadas)

El sistema de migraciones está diseñado para que cada tabla se cree mediante un método dedicado, manteniendo el código claro, mantenible e idempotente.

A continuación se explica paso a paso cómo crear una nueva tabla dentro de este sistema.

1️⃣ Crear un método por tabla

Cada tabla debe tener su propio método privado dentro del comando:

private function createProductosTable($schemaManager, OutputInterface $output): void

🔹 El nombre debe comenzar con create y terminar con Table por convención.

2️⃣ Definir el nombre de la tabla

Dentro del método, define el nombre de la tabla:

$tableName = 'productos';

Verificar si la tabla ya existe

Esto evita errores y hace que la migración sea segura de ejecutar múltiples veces:

if (in_array($tableName, $schemaManager->listTableNames())) {
$output->writeln("ℹ La tabla <comment>$tableName</comment> ya existe.");
return;
}

✔ Esta es la clave para que la migración sea idempotente.

4️⃣ Crear la instancia de la tabla

Usa Doctrine DBAL para definir la estructura:

$table = new Table($tableName);

5️⃣ Agregar columnas

Cada columna se define con addColumn:

$table->addColumn('id', 'integer', [
'autoincrement' => true,
'unsigned' => true
]);

$table->addColumn('nombre', 'string', ['length' => 150]);
$table->addColumn('precio', 'decimal', ['precision' => 10, 'scale' => 2]);
$table->addColumn('activo', 'boolean', ['notnull' => false]);

Tipos comunes:

integer

string

text

boolean

decimal

date, datetime

6️⃣ Definir la clave primaria

Toda tabla debe tener una primary key:

$table->setPrimaryKey(['id']);
7️⃣ Agregar índices (opcional pero recomendado)
$table->addUniqueIndex(['nombre'], 'uniq_productos_nombre');
$table->addIndex(['activo'], 'idx_productos_activo');

8️⃣ Crear la tabla físicamente

Finalmente, se ejecuta la creación:

$schemaManager->createTable($table);
$output->writeln("✔ Tabla <info>$tableName</info> creada.");

9️⃣ Manejar errores

Envuelve todo en un bloque try/catch:

try {
// definición de la tabla
} catch (SchemaException $e) {
$output->writeln("<error>Error en $tableName: {$e->getMessage()}</error>");
}

🔟 Registrar la migración

Para que la tabla se cree, debes llamar el método desde execute():

$this->createProductosTable($schemaManager, $output);

Si no se llama aquí, la migración no se ejecutará.

🧪 Ejemplo completo

private function createProductosTable($schemaManager, OutputInterface $output): void
{
$tableName = 'productos';

try {

if (in_array($tableName, $schemaManager->listTableNames())) {
$output->writeln("ℹ La tabla <comment>$tableName</comment> ya existe.");
return;
}

$table = new Table($tableName);


$table->addColumn('id', 'integer', [
'autoincrement' => true,
'unsigned' => true
]);


$table->addColumn('nombre', 'string', ['length' => 150]);
$table->addColumn('precio', 'decimal', ['precision' => 10, 'scale' => 2]);
$table->addColumn('activo', 'boolean', ['notnull' => false]);


$table->setPrimaryKey(['id']);


$schemaManager->createTable($table);


$output->writeln("✔ Tabla <info>$tableName</info> creada.");
} catch (SchemaException $e) {
$output->writeln("<error>Error en $tableName: {$e->getMessage()}</error>");
}
}

▶️ Cómo ejecutar las migraciones

Desde la raíz del proyecto ejecuta:

php arco database:migrate

Salida esperada

Creando tabla anidada...
✔ Tabla anidada creada.
ℹ La tabla menu ya existe.
✔ Migraciones completadas.