| Librería actual | Estado | Reemplazo recomendado | Razón |
|---|---|---|---|
| CentOS 7 | EOL jun 2024 | Rocky Linux 9 | Sucesor natural, compatible con RHEL 9, soporte hasta 2032 |
| PHPExcel 1.8.0 | Abandonado | PhpSpreadsheet 2.x | Sucesor oficial del mismo autor, API muy similar |
| Bootstrap DatetimePicker | Abandonado | Flatpickr 4.x | Sin dependencias, 16KB, activo, fácil integración |
| Morris.js + Raphael.js | Abandonado 2014 | Chart.js 4.x | Estándar de la industria, sin dependencias, documentación excelente |
| SweetAlert 1.x | Abandonado | SweetAlert2 11.x | Sucesor directo, API base compatible, activo |
| Moment.js 2.9.0 | Mantenimiento | Day.js 1.x | API casi idéntica, 2 KB, activo y recomendado por Moment |
| AngularJS 1.5.9 + UI-Bootstrap | EOL dic 2021 | Alpine.js 3.x | Sin build step, convive con jQuery, directivas similares a AngularJS |
| Bootstrap 3.4.1 + Material Design fork | Sin soporte | Bootstrap 5.3.x | Estándar actual, sin jQuery, activo |
| Font Awesome 4.5.0 | Sin actualizaciones | Font Awesome 6 Free | Mismo sistema de iconos, ~1400 iconos nuevos, shim de compatibilidad |
| FullCalendar 2.5.0 | API obsoleta | FullCalendar 6.x | Misma librería, API moderna, sin Moment ni jQuery |
| Socket.IO 1.4.5 | Sin uso (huérfano) | Eliminar | No hay referencias en ningún archivo del proyecto |
| CodeIgniter 3.0.3 | EOL | CodeIgniter 4.x (Fase 7) | Reescritura completa; se aborda al final para no bloquear fases anteriores |
¿Por qué Alpine.js y no Vue.js o React?
Análisis técnico comparativo considerando el stack actual del proyecto (PHP · CodeIgniter · jQuery · Apache)
| Criterio | Alpine.js 3.x ✓ | Vue.js 3 | React 18 |
|---|---|---|---|
| Build step requerido | No — solo un <script> | Sí (Vite + npm) | Sí (Vite/Webpack + npm) |
| Tamaño (min + gzip) | 15 KB | 33 KB | 45 KB |
| Integración con PHP/Apache | Directa — idéntica a jQuery | Requiere configuración | Requiere configuración |
| Convive con jQuery | Sí, sin conflicto | Parcialmente | Conflictos frecuentes |
| Directivas declarativas en HTML | Sí (como AngularJS) | Sí | No (requiere JSX) |
| Curva de aprendizaje | Muy baja (1–2 días) | Media (2–4 semanas) | Alta (1–2 meses) |
| Migración módulo a módulo | Sí — coexiste con AngularJS | Complejo | Requiere reescritura total |
| Adopción en ecosistema PHP | Enorme (Laravel, Livewire) | Media | Baja |
Razones técnicas en detalle
<script> en el HTML y listo.x-model, @click, x-show), no en archivos de componentes separados. El equipo actual que conoce AngularJS adoptará Alpine.js en días, no en semanas.¿Quién usa Alpine.js en el mundo real?
Alpine.js es el estándar de facto para interactividad JavaScript en el ecosistema PHP/Laravel. No es una herramienta experimental.
Conclusión: Alpine.js no es una apuesta experimental. Es la herramienta que el ecosistema PHP ha adoptado masivamente para exactamente este caso de uso: modernizar interactividad en aplicaciones server-side sin reescribir ni agregar complejidad de build. Para Mas Me Dan, reduce el riesgo de migración, acelera los tiempos, y mantiene el stack familiar para el equipo.
Preparación y Baseline
0.1 — Entorno de Testing
- Confirmar que testing tiene la misma versión de PHP, MySQL y configuración de Apache que producción.
- Configurar sincronización documentada de BD (dump de producción → testing) con datos anónimos si es posible.
- Bloquear testing por IP o autenticación básica HTTP para que ninguna sucursal lo vea.
0.2 — Git y Proceso de Deploys
- Verificar que el repositorio Git tiene una rama
masterlimpia y al día. - Crear ramas de trabajo por fase:
migration/fase-1a-servidor,migration/fase-1b-php8, etc. - Documentar proceso de deploy a producción (script / rsync / FTP).
- Política de backups antes de cada deploy: dump SQL + zip de
application/yres/con timestamp.
0.3 — Limpieza de Archivos Huérfanos
- Eliminar
res/js/socket.io-1.4.5.js— no está referenciado en ningún archivo del proyecto. - Eliminar
res/js/jquery-1.10.2.min.jsyjquery-2.1.4.min.js— versiones obsoletas sin uso activo. - Eliminar
res/js/ui-bootstrap-tpls-2.1.2.min.js— versión intermedia sin uso activo. - Documentar qué módulos usan
ui-bootstrap-tpls-0.12.1vs2.5.0.
0.4 — Inventario de Módulos con AngularJS
- Listar todas las vistas que usan directivas AngularJS (
ng-*) para conocer el alcance de la Fase 6.
Servidor: CentOS 7 → Rocky Linux 9
¿Por qué Rocky Linux 9?
- Sucesor natural de CentOS, binariamente compatible con RHEL 9.
- Mismos comandos (
dnf/yum), misma estructura de directorios — curva de aprendizaje mínima. - Soporte garantizado hasta mayo de 2032.
- PHP 8.2/8.3, MariaDB 10.11, Apache 2.4 disponibles desde repositorios oficiales.
Argumento de seguridad para el comité
Estrategia: Servidor Paralelo (Blue-Green Deployment)
No se migra el servidor existente en caliente. Se levanta un servidor nuevo con Rocky Linux 9 en paralelo, se prueba completamente, y el cutover es un simple cambio de IP en la VPN.
Tiempo de downtime real: 15–30 minutos (solo el cambio de IP en la VPN). Rollback disponible en menos de 5 minutos.
Paso A — Inventario de configuración de CentOS 7
- Documentar versiones:
php -v,httpd -v,mysql --version. - Exportar extensiones PHP activas:
php -m > extensiones_php.txt. - Exportar configuración de Apache:
/etc/httpd/conf/httpd.confy todos los vhosts enconf.d/. - Listar crontabs:
crontab -ly/etc/cron.d/. - Documentar reglas de firewall:
firewall-cmd --list-all. - Exportar BD completa:
mysqldump --all-databases > backup_completo.sql. - Guardar todo en el repo bajo
infra/centos7-config/.
Paso B — Instalación de Rocky Linux 9
dnf install httpd -y
systemctl enable --now httpd
# PHP 8.2 via repositorio Remi
dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm -y
dnf module reset php && dnf module enable php:remi-8.2
dnf install php php-mysqlnd php-mbstring php-gd php-curl php-zip php-xml php-intl php-json php-opcache php-fpm -y
# MariaDB 10.11
dnf install mariadb-server -y
systemctl enable --now mariadb && mysql_secure_installation
# Restaurar base de datos
mysql -u root -p < backup_completo.sql
- Copiar el código del proyecto al nuevo servidor (mismo path que en CentOS 7).
- Replicar vhosts, crontabs y variables de entorno desde el inventario del Paso A.
- Ajustar permisos (
chown,chmod) y configurar SELinux si está activo.
Paso C — Pruebas en Rocky Linux 9
- Acceder al nuevo servidor por IP directa desde el equipo de desarrollo.
- QA funcional completo: todos los módulos, PDFs, Excel, consultas a BD.
- Verificar logs:
tail -f /var/log/httpd/error_log. - Probar acceso desde al menos 2 sucursales piloto apuntando temporalmente al nuevo servidor.
Paso D — Cutover a Producción
- Programar ventana nocturna (15–30 min). Comunicar a supervisores con 48h de anticipación.
- Hacer dump final de la BD de CentOS 7 justo antes del cutover (datos del mismo día).
- Importar dump final en Rocky Linux 9.
- Cambiar IP en la configuración VPN → sucursales apuntan al servidor nuevo.
- Verificar acceso desde 3–5 sucursales piloto distribuidas.
- Mantener CentOS 7 en standby 72 horas — no apagar hasta confirmar estabilidad total.
- Monitorear logs durante 48 horas post-cutover. Apagar CentOS 7 al confirmar estabilidad.
Correcciones de Compatibilidad PHP 8.2
Errores comunes PHP 5.6 → PHP 8.2
| Función / Patrón | En PHP 5.6 | En PHP 8.2 | Solución |
|---|---|---|---|
| ereg(), ereg_replace() | Funcionaba | Eliminada | Reemplazar con preg_match(), preg_replace() |
| split() | Funcionaba | Eliminada | Usar explode() o preg_split() |
| each() | Funcionaba | Eliminada | Reemplazar con foreach |
| create_function() | Funcionaba | Eliminada | Usar closures anónimas function() {} |
| mysql_* functions | Deprecada | Eliminada | CI3 ya usa mysqli — verificar código legado |
| strpos() con null | Silencioso | Warning | Verificar valores antes de llamar a la función |
Parches específicos de CodeIgniter 3 para PHP 8
system/core/Security.php— ajuste encsrf_verify()por cambio en manejo denull.system/database/drivers/mysqli/mysqli_driver.php— ajuste en inicialización de conexión.system/core/Input.php— ajuste en_fetch_from_array()por tipos estrictos.system/core/Utf8.php— ajuste en detección de encoding.
Proceso de corrección
- Activar reporte completo en testing:
error_reporting(E_ALL)enindex.php. - Navegar todos los módulos y registrar cada error/warning en el log de PHP.
- Corregir errores fatales primero → deprecaciones → warnings.
- Commits atómicos por archivo corregido en
migration/fase-1b-php8. - QA funcional completo tras cada lote de correcciones.
- Desactivar reporte de errores ampliado antes del deploy a producción.
Dependencias PHP Críticas
2.1 — PHPExcel → PhpSpreadsheet 2.x
PHPExcel no funciona con PHP 8. PhpSpreadsheet es su sucesor oficial del mismo autor.
| PHPExcel (actual) | PhpSpreadsheet (nuevo) |
|---|---|
new PHPExcel() | new \PhpOffice\PhpSpreadsheet\Spreadsheet() |
PHPExcel_IOFactory::load($file) | \PhpOffice\PhpSpreadsheet\IOFactory::load($file) |
PHPExcel_IOFactory::createWriter($obj, 'Excel2007') | IOFactory::createWriter($obj, 'Xlsx') |
$sheet->setCellValue('A1', $val) | Idéntico — sin cambio |
- Identificar todos los archivos PHP que instancian
PHPExcelo usanPHPExcel_IOFactory. - Instalar PhpSpreadsheet via Composer o manualmente.
- Probar cada reporte Excel en testing. Deploy a producción.
2.2 — AWS SDK 3.340+
- Actualizar
application/libraries/aws/a la versión 3.340+ (requiere PHP 8.1+, ya cumplido). - Verificar que
application/libraries/Aws.php(wrapper interno) sigue siendo compatible. - Probar todas las operaciones S3/AWS del sistema.
2.3 — TCPDF 6.7.x
- Actualizar
application/libraries/tcpdf/a la versión 6.7.x. - Probar generación de todos los PDFs existentes (contratos, recibos, etc.) en testing.
Actualizaciones JS Menores
jQuery 3.4.1 → 3.7.x · SweetAlert → SweetAlert2 · Select2 → 4.1.x
- jQuery: Reemplazar
jquery-3.4.1.min.jscon 3.7.x. API compatible, incluye fixes de seguridad. - SweetAlert2: Reemplazar archivos. Agregar shim temporal:
window.swal = (t,m,i) => Swal.fire({title:t, text:m, icon:i})para mantener llamadas existentes sin romper nada. - Select2 4.1.x: Reemplazar archivos. API compatible hacia atrás.
- Underscore.js 1.13.x: Reemplazar archivo. API compatible hacia atrás.
Bootstrap 5 + Font Awesome 6
Cambios principales Bootstrap 3 → Bootstrap 5
| Bootstrap 3 | Bootstrap 5 | Nota |
|---|---|---|
col-xs-* | col-* | Breakpoint xs eliminado |
hidden-xs, visible-md | d-none d-md-block | Nuevo sistema de visibilidad |
panel, panel-body | card, card-body | Componente renombrado |
btn-default | btn-secondary | |
pull-left / pull-right | float-start / float-end | |
data-toggle, data-dismiss, data-target | data-bs-toggle, data-bs-dismiss, data-bs-target | Todos los atributos data- cambian |
| Glyphicons | Eliminados → Font Awesome 6 |
Orden de migración de módulos (menor → mayor riesgo)
Font Awesome 6 — estrategia con shim
Se despliega FA6 con el shim de compatibilidad que convierte automáticamente clases fa fa-* al nuevo formato. Esto permite desplegar FA6 sin cambiar ningún ícono de inmediato.
<link rel="stylesheet" href="res/css/font-awesome-6/css/all.min.css">
<link rel="stylesheet" href="res/css/font-awesome-6/css/v4-shims.min.css">
Fechas, Calendario y Gráficos
Bootstrap DatetimePicker → Flatpickr 4.x
Flatpickr no depende de Bootstrap ni de Moment.js — funciona de forma completamente independiente.
$('#fecha').datetimepicker({ format: 'DD/MM/YYYY', locale: 'es' });
// Después (Flatpickr)
flatpickr('#fecha', { dateFormat: 'd/m/Y', locale: 'es' });
Moment.js → Day.js — API casi idéntica
moment().format('DD/MM/YYYY')
moment('2026-01-15').add(30, 'days').format('DD/MM/YYYY')
// Después (Day.js) — mismo código, diferente nombre
dayjs().format('DD/MM/YYYY')
dayjs('2026-01-15').add(30, 'days').format('DD/MM/YYYY')
Morris.js + Raphael.js → Chart.js 4.x
Morris.Bar({ element: 'chart', data: [...], xkey: 'mes', ykeys: ['valor'] });
// Después (Chart.js 4)
new Chart(document.getElementById('chart'), {
type: 'bar',
data: { labels: data.map(d => d.mes), datasets: [{ data: data.map(d => d.valor) }] }
});
AngularJS → Alpine.js
Equivalencias de directivas clave
| AngularJS (actual) | Alpine.js (nuevo) |
|---|---|
ng-app="miApp" | x-data="miComponente()" |
ng-model="variable" | x-model="variable" |
ng-click="funcion()" | @click="funcion()" |
ng-show="cond" | x-show="cond" |
ng-if="cond" | x-if="cond" |
ng-repeat="item in lista" | template x-for="item in lista" |
ng-class="{'clase': cond}" | :class="{'clase': cond}" |
{{ variable }} | <span x-text="variable"> |
$http.get(url) | fetch(url).then(r => r.json()) |
Orden de migración de módulos (menor → mayor complejidad AngularJS)
ng-show/ng-hide simplesng-modelng-repeat$http)CodeIgniter 3 → CodeIgniter 4
CI4 es una reescritura completa (namespaces PHP, PSR-4, sin compatibilidad directa con CI3). Se aborda al final porque las fases anteriores tienen mayor impacto inmediato en seguridad.
Estrategia recomendada: Strangler Fig a nivel de framework. Instalar CI4 como proyecto separado, migrar un módulo a la vez, y usar un proxy en Apache para enrutar las rutas del módulo migrado a CI4 mientras el resto sigue en CI3. Al final, CI3 queda sin rutas activas y se elimina.
- Backup de BD completo en S3/local.
- Backup de archivos
application/yres/con timestamp. - Comunicado a supervisores de sucursales si la ventana afecta el horario de apertura.
- Deploy en ventana nocturna.
- Monitorear logs las primeras 2 horas post-deploy.
- QA express: login, crear empeño, PDF, Excel, acceso desde 2 sucursales piloto.
- Plan de rollback: revertir commit → deploy versión anterior.
- Rocky Linux 9 probado al menos 3 días en testing.
- Dump final de BD de CentOS 7 importado en Rocky Linux 9 (datos del día).
- Ventana nocturna comunicada con 48h de anticipación.
- Cambiar IP en configuración VPN.
- Verificar acceso desde 3–5 sucursales piloto distribuidas.
- CentOS 7 en standby 72 horas antes de apagar.
- Rollback: revertir IP en VPN → sucursales vuelven a CentOS 7 en < 5 min.
Punto de entrada recomendado: Fase 0 (preparación) → Fase 1A (servidor).
Sin un servidor moderno con PHP 8.2, ninguna otra fase puede avanzar de forma sostenida.
La Fase 1A y 1B son el desbloqueante de todo el plan.