Base de Datos

Migraciones de Base de Datos en Perfex CRM

J. Negro 18 Dic 2025 15 min lectura
Volver al Blog

¿Qué son las Migraciones?

Las migraciones son archivos PHP que describen cambios en el esquema de base de datos. Permiten versionar tu base de datos de forma similar a como Git versiona tu código.

💡 Ventajas de las Migraciones

• Control de versiones del esquema de BD
• Despliegues consistentes entre entornos
• Rollback en caso de problemas
• Historial completo de cambios

Regla de Oro: Doble Trabajo

En Perfex CRM, cada cambio de base de datos requiere actualizar DOS archivos:

  1. Migración en migrations/XXX_version_XXX.php
  2. install.php - El estado consolidado de todas las migraciones

⚠️ ¿Por qué doble trabajo?

El install.php se ejecuta en instalaciones nuevas (no hay migraciones previas). Las migraciones se ejecutan en actualizaciones (ya existe la BD). Si solo actualizas uno, tendrás inconsistencias.

Estructura de una Migración

Las migraciones deben seguir el patrón de nomenclatura y extender App_module_migration:

<?php
defined('BASEPATH') or exit('No direct script access allowed');

/**
 * Migración: Añadir tabla de auditoría
 * Versión: 2.3.5
 * Fecha: 2025-12-18
 */
class Migration_Version_235 extends App_module_migration
{
    /**
     * Ejecutar migración (actualización)
     */
    public function up()
    {
        $CI = &get_instance();

        // Verificar si la tabla NO existe antes de crear
        if (!$CI->db->table_exists(db_prefix() . 'mi_modulo_audit')) {
            $CI->db->query("
                CREATE TABLE `" . db_prefix() . "mi_modulo_audit` (
                    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
                    `action` VARCHAR(50) NOT NULL,
                    `entity_type` VARCHAR(50) NOT NULL,
                    `entity_id` INT(11) NOT NULL,
                    `staff_id` INT(11) NOT NULL,
                    `old_value` TEXT,
                    `new_value` TEXT,
                    `datecreated` DATETIME NOT NULL,
                    PRIMARY KEY (`id`),
                    INDEX `idx_entity` (`entity_type`, `entity_id`),
                    INDEX `idx_staff` (`staff_id`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
            ");
        }

        // Añadir columna a tabla existente
        if (!$CI->db->field_exists('last_audit_date', db_prefix() . 'mi_modulo_items')) {
            $CI->db->query("
                ALTER TABLE `" . db_prefix() . "mi_modulo_items`
                ADD COLUMN `last_audit_date` DATETIME NULL AFTER `datecreated`;
            ");
        }
    }

    /**
     * Revertir migración (rollback)
     */
    public function down()
    {
        $CI = &get_instance();

        // Eliminar tabla
        if ($CI->db->table_exists(db_prefix() . 'mi_modulo_audit')) {
            $CI->db->query('DROP TABLE `' . db_prefix() . 'mi_modulo_audit`');
        }

        // Eliminar columna
        if ($CI->db->field_exists('last_audit_date', db_prefix() . 'mi_modulo_items')) {
            $CI->db->query("
                ALTER TABLE `" . db_prefix() . "mi_modulo_items`
                DROP COLUMN `last_audit_date`;
            ");
        }
    }
}

Paso a Paso: Crear una Migración

1Crear el archivo de migración

El nombre debe seguir el patrón: {version}_version_{version}.php

# Ejemplo: versión 2.3.5
modules/mi_modulo/migrations/235_version_235.php

2Actualizar install.php

Añade los mismos cambios de esquema al archivo de instalación:

// install.php - Añadir al final

// v2.3.5 - Tabla de auditoría
if (!$CI->db->table_exists(db_prefix() . 'mi_modulo_audit')) {
    $CI->db->query("
        CREATE TABLE `" . db_prefix() . "mi_modulo_audit` (
            ...
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    ");
}

3Actualizar versión del módulo

En mi_modulo.php, actualiza en DOS lugares:

// Línea ~11 (comentario header)
/*
 * Version: 2.3.5  ← ACTUALIZAR
 */

// Línea ~20 (constante)
define('MI_MODULO_VERSION', '2.3.5'); // ← ACTUALIZAR

4Actualizar CHANGELOG.md

## [2.3.5] - 2025-12-18

### Añadido
- Nueva tabla de auditoría para tracking de cambios
- Campo `last_audit_date` en items

Verificación de Migraciones

Perfex almacena la versión actual de cada módulo en tblmodules:

# Verificar versión actual del módulo
mysql -u root mi_base_de_datos -e "
SELECT module_name, installed_version
FROM tblmodules
WHERE module_name = 'mi_modulo';
"

🚨 Error Común: Versión no actualizada

Si la migración no se ejecuta, verifica que installed_version en tblmodules sea menor que la nueva versión. Perfex solo ejecuta migraciones con número mayor al instalado.

Operaciones Comunes

Añadir columna

if (!$CI->db->field_exists('nueva_columna', db_prefix() . 'tabla')) {
    $CI->db->query("
        ALTER TABLE `" . db_prefix() . "tabla`
        ADD COLUMN `nueva_columna` VARCHAR(255) NULL DEFAULT NULL;
    ");
}

Modificar columna

$CI->db->query("
    ALTER TABLE `" . db_prefix() . "tabla`
    MODIFY COLUMN `columna` TEXT NOT NULL;
");

Añadir índice

// Verificar si el índice no existe
$index = $CI->db->query("
    SHOW INDEX FROM `" . db_prefix() . "tabla`
    WHERE Key_name = 'idx_columna'
")->row();

if (!$index) {
    $CI->db->query("
        CREATE INDEX `idx_columna` ON `" . db_prefix() . "tabla` (`columna`);
    ");
}

Checklist de Migraciones

✅ Antes de hacer commit

□ ¿Creé la migración con el nombre correcto?
□ ¿Actualicé install.php con los mismos cambios?
□ ¿Actualicé la versión en mi_modulo.php (2 lugares)?
□ ¿Actualicé CHANGELOG.md?
□ ¿Usé db_prefix() en todas las queries?
□ ¿Verifiqué existencia antes de crear/modificar?

JN

J. Negro

Desarrollador especializado en Perfex CRM con más de 5 años de experiencia creando módulos empresariales. Fundador de SalesCloud.