crear migration en laravel

PHOTO EMBED

Tue Aug 26 2025 16:13:26 GMT+0000 (Coordinated Universal Time)

Saved by @jrg_300i #docker

#!/bin/bash

# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Función para mostrar mensajes de error
error() {
    echo -e "${RED}Error: $1${NC}" >&2
}

# Función para mostrar mensajes de éxito
success() {
    echo -e "${GREEN}$1${NC}"
}

# Función para mostrar advertencias
warning() {
    echo -e "${YELLOW}Advertencia: $1${NC}"
}

# Función para mostrar información
info() {
    echo -e "${BLUE}$1${NC}"
}

# Función para mostrar detalles
detail() {
    echo -e "${CYAN}$1${NC}"
}

# Función para normalizar nombres (remover guiones bajos y convertir a minúsculas)
normalizar_nombre() {
    echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/_//g'
}

# Función para obtener migraciones existentes
obtener_migraciones_existentes() {
    local migraciones=()
    if [ -d "database/migrations" ]; then
        while IFS= read -r -d '' archivo; do
            # Extraer el nombre de la tabla del archivo de migración
            local nombre_archivo=$(basename "$archivo")
            # Buscar varios patrones comunes de migraciones
            if [[ "$nombre_archivo" =~ create_(.*)_table\.php ]] ||
               [[ "$nombre_archivo" =~ _(.*)_table\.php ]] ||
               [[ "$nombre_archivo" =~ create_(.*)\.php ]] ||
               [[ "$nombre_archivo" =~ _(.*)\.php ]]; then
                migraciones+=("${BASH_REMATCH[1]}")
            fi
        done < <(find database/migrations -name "*.php" -print0 2>/dev/null)
    fi
    echo "${migraciones[@]}"
}

# Función para verificar si una migración ya existe (comparación normalizada)
migracion_existe() {
    local tabla="$1"
    local migraciones_existentes=($(obtener_migraciones_existentes))
    
    # Normalizar el nombre de la tabla a verificar
    local tabla_normalizada=$(normalizar_nombre "$tabla")
    
    for migracion in "${migraciones_existentes[@]}"; do
        # Normalizar el nombre de la migración existente
        local migracion_normalizada=$(normalizar_nombre "$migracion")
        
        if [ "$migracion_normalizada" == "$tabla_normalizada" ]; then
            return 0 # true - existe
        fi
    done
    return 1 # false - no existe
}

# Función para obtener el nombre real del archivo de migración existente
obtener_nombre_archivo_existente() {
    local tabla="$1"
    local migraciones_existentes=($(obtener_migraciones_existentes))
    
    local tabla_normalizada=$(normalizar_nombre "$tabla")
    
    for migracion in "${migraciones_existentes[@]}"; do
        local migracion_normalizada=$(normalizar_nombre "$migracion")
        
        if [ "$migracion_normalizada" == "$tabla_normalizada" ]; then
            # Encontrar el archivo real
            archivo_existente=$(find database/migrations -name "*${migracion}*" -print -quit 2>/dev/null)
            if [ -n "$archivo_existente" ]; then
                echo "$(basename "$archivo_existente")"
                return
            fi
        fi
    done
    echo ""
}

# Función para verificar si una palabra está en plural (inglés y español)
es_plural() {
    local palabra="$1"
    local palabra_lower=$(echo "$palabra" | tr '[:upper:]' '[:lower:]')
    
    # Reglas para plural en inglés
    local plural_ingles=(
        "s$" "es$" "ies$" "ves$" "xes$" "zes$" "ches$" "shes$"
    )
    
    # Reglas para plural en español
    local plural_espanol=(
        "s$" "es$" "ces$" "ses$" "res$" "nes$"
    )
    
    # Verificar reglas en inglés
    for regla in "${plural_ingles[@]}"; do
        if [[ "$palabra_lower" =~ $regla ]]; then
            return 0 # true - es plural
        fi
    done
    
    # Verificar reglas en español
    for regla in "${plural_espanol[@]}"; do
        if [[ "$palabra_lower" =~ $regla ]]; then
            return 0 # true - es plural
        fi
    done
    
    # Palabras comunes que son plurales
    local plurales_comunes=(
        "people" "children" "men" "women" "feet" "teeth" "mice" "geese"
        "data" "criteria" "phenomena" "personas" "gentes" "naciones"
        "usuarios" "personas" "productos" "categorias" "articulos"
    )
    
    for plural in "${plurales_comunes[@]}"; do
        if [ "$palabra_lower" == "$plural" ]; then
            return 0 # true - es plural
        fi
    done
    
    return 1 # false - no es plural
}

# Función para sugerir plural en inglés (convención Laravel)
sugerir_plural() {
    local palabra="$1"
    local idioma="${2:-en}" # default inglés
    
    # Convertir a minúsculas para procesamiento
    local palabra_lower=$(echo "$palabra" | tr '[:upper:]' '[:lower:]')
    local resultado=""
    
    if [ "$idioma" == "en" ]; then
        # Reglas de pluralización en inglés
        if [[ "$palabra_lower" =~ y$ ]] && ! [[ "$palabra_lower" =~ [aeiou]y$ ]]; then
            resultado="${palabra_lower%y}ies"
        elif [[ "$palabra_lower" =~ f$ ]]; then
            resultado="${palabra_lower%f}ves"
        elif [[ "$palabra_lower" =~ fe$ ]]; then
            resultado="${palabra_lower%fe}ves"
        elif [[ "$palabra_lower" =~ s$ ]] || [[ "$palabra_lower" =~ x$ ]] || [[ "$palabra_lower" =~ z$ ]] || 
             [[ "$palabra_lower" =~ ch$ ]] || [[ "$palabra_lower" =~ sh$ ]]; then
            resultado="${palabra_lower}es"
        else
            resultado="${palabra_lower}s"
        fi
    else
        # Reglas básicas de pluralización en español
        if [[ "$palabra_lower" =~ [áéíóú]$ ]]; then
            resultado="${palabra_lower}es"
        elif [[ "$palabra_lower" =~ z$ ]]; then
            resultado="${palabra_lower%z}ces"
        elif [[ "$palabra_lower" =~ [aeiou]$ ]]; then
            resultado="${palabra_lower}s"
        elif [[ "$palabra_lower" =~ [bcdfghjklmnpqrstvwxyz]$ ]]; then
            resultado="${palabra_lower}es"
        else
            resultado="${palabra_lower}s"
        fi
    fi
    
    # Mantener capitalización original si la palabra comenzaba con mayúscula
    if [[ "$palabra" =~ ^[A-Z] ]]; then
        resultado="$(echo "${resultado:0:1}" | tr '[:lower:]' '[:upper:]')${resultado:1}"
    fi
    
    echo "$resultado"
}

# Mostrar migraciones existentes
mostrar_migraciones_existentes() {
    local migraciones_existentes=($(obtener_migraciones_existentes))
    
    if [ ${#migraciones_existentes[@]} -eq 0 ]; then
        info "No hay migraciones existentes en la carpeta database/migrations"
    else
        info "Migraciones existentes:"
        for migracion in "${migraciones_existentes[@]}"; do
            detail "  - $migracion"
        done
        echo ""
    fi
}

# Función para solicitar nombre de tabla con todas las validaciones
solicitar_nombre_tabla() {
    local numero_tabla="$1"
    local tablas_existentes=("$2") # Tablas ya ingresadas en esta sesión
    
    while true; do
        read -p "Ingrese el nombre de la tabla $numero_tabla: " nombre_tabla
        
        # Validar que no esté vacío
        if [ -z "$nombre_tabla" ]; then
            error "El nombre no puede estar vacío."
            continue
        fi
        
        # Validar formato
        if [[ ! "$nombre_tabla" =~ ^[a-zA-Z0-9_áéíóúÁÉÍÓÚñÑ]+$ ]]; then
            error "El nombre contiene caracteres no válidos."
            continue
        fi
        
        # Verificar si está en plural
        if ! es_plural "$nombre_tabla"; then
            warning "El nombre '$nombre_tabla' parece estar en singular."
            
            # Ofrecer sugerencias en inglés y español
            sugerencia_en=$(sugerir_plural "$nombre_tabla" "en")
            sugerencia_es=$(sugerir_plural "$nombre_tabla" "es")
            
            echo "Sugerencias:"
            echo "  1) Inglés (recomendado): $sugerencia_en"
            echo "  2) Español: $sugerencia_es"
            echo "  3) Mantener '$nombre_tabla'"
            
            read -p "Seleccione una opción (1/2/3): " opcion_plural
            
            case $opcion_plural in
                1) nombre_tabla="$sugerencia_en" ;;
                2) nombre_tabla="$sugerencia_es" ;;
                3) info "Manteniendo: $nombre_tabla" ;;
                *) 
                    error "Opción no válida. Manteniendo nombre original."
                    ;;
            esac
        fi
        
        # Verificar si la migración ya existe en el sistema (comparación normalizada)
        if migracion_existe "$nombre_tabla"; then
            warning "¡La migración para '$nombre_tabla' ya existe!"
            
            # Mostrar el archivo existente
            archivo_existente=$(obtener_nombre_archivo_existente "$nombre_tabla")
            if [ -n "$archivo_existente" ]; then
                detail "Archivo existente: $archivo_existente"
            fi
            
            # Pedir nuevo nombre inmediatamente
            read -p "Por favor, ingrese un nombre diferente: " nombre_tabla
            
            # Continuar el ciclo para validar el nuevo nombre
            continue
        fi
        
        # Verificar si ya fue ingresado en esta misma sesión (comparación normalizada)
        for tabla_existente in "${tablas_existentes[@]}"; do
            if [ "$(normalizar_nombre "$tabla_existente")" == "$(normalizar_nombre "$nombre_tabla")" ]; then
                warning "El nombre '$nombre_tabla' ya fue ingresado en esta sesión."
                read -p "Por favor, ingrese un nombre diferente: " nombre_tabla
                continue 2
            fi
        done
        
        # Si llegamos aquí, el nombre es válido, no existe y no es duplicado
        echo "$nombre_tabla"
        break
    done
}

# Validar que estamos en un proyecto Laravel
if [ ! -f "artisan" ]; then
    error "No se encontró el archivo artisan. Asegúrate de estar en el directorio raíz de un proyecto Laravel."
    exit 1
fi

# Validar que PHP está disponible
if ! command -v php &> /dev/null; then
    error "PHP no está instalado o no está en el PATH."
    exit 1
fi

# Mostrar migraciones existentes al inicio
mostrar_migraciones_existentes

# Solicitar y validar la cantidad de tablas
while true; do
    read -p "Ingrese la cantidad de tablas que desea crear: " cantidad_tablas
    
    if [[ ! "$cantidad_tablas" =~ ^[0-9]+$ ]]; then
        error "Por favor, ingrese un número válido."
        continue
    fi
    
    if [ "$cantidad_tablas" -lt 1 ]; then
        error "La cantidad debe ser al menos 1."
        continue
    fi
    
    break
done

# Inicializar arreglo para almacenar los nombres de las tablas
tablas=()

info "Convenciones de Laravel:"
info "- Nombres de tablas en PLURAL (inglés preferido)"
info "- Ejemplos: users, products, categories, posts, comments"
info "- También se acepta español: usuarios, productos, categorías"

# Solicitar los nombres de las tablas con validación inmediata
for ((i=1; i<=cantidad_tablas; i++)); do
    nombre_tabla=$(solicitar_nombre_tabla $i "${tablas[@]}")
    
    tablas+=("$nombre_tabla")
    success "Tabla agregada: $nombre_tabla"
done

if [ ${#tablas[@]} -eq 0 ]; then
    warning "No se agregaron tablas para crear migraciones."
    exit 0
fi

# Mostrar resumen antes de proceder
echo -e "\n${YELLOW}Resumen de migraciones a crear:${NC}"
for table in "${tablas[@]}"; do
    echo "  - create_${table}_table"
done

# Confirmar antes de ejecutar
read -p $'\n¿Desea continuar con la creación de las migraciones? (s/N): ' confirmar

if [[ ! "$confirmar" =~ ^[SsYy]$ ]] && [ -n "$confirmar" ]; then
    warning "Operación cancelada por el usuario."
    exit 0
fi

# Crear las migraciones
echo -e "\nCreando migraciones..."
for table in "${tablas[@]}"; do
    echo "Creando migración para: $table"
    
    if php artisan make:migration "create_${table}_table" --quiet; then
        success "✓ Migración para '$table' creada exitosamente."
    else
        error "✗ Error al crear la migración para '$table'"
    fi
done

# Mostrar migraciones actualizadas
echo -e "\n"
mostrar_migraciones_existentes

success "¡Proceso completado! Se crearon ${#tablas[@]} migraciones."
content_copyCOPY