Migrar una aplicación de PHP 5.3 a PHP 8.4 con ayuda de la IA no consiste en pedirle que modernice el código y esperar. Consiste en usarla para entender el proyecto, ordenar el trabajo y revisar mejor el resultado, sin soltar el control de lo que acaba en producción. Este es el proceso que seguimos, dónde nos ayudó de verdad y dónde no.
Cuando se habla de IA en desarrollo, la conversación empieza casi siempre por lo mismo: cuánto código puede escribir y en cuánto tiempo.
Es normal, porque es la parte que se ve.
Describes lo que necesitas, esperas unos segundos y aparece algo que hace más o menos lo que pedías. La IA no protesta, no discute la arquitectura y casi siempre entrega algo que arranca.
El problema está justo ahí, en ese «arranca».
Un fragmento de código puede funcionar perfectamente y duplicar algo que ya existía. Puede resolver el caso que le describiste e ignorar los tres que no mencionaste. Puede seguir un patrón correcto en abstracto y saltarse las normas del proyecto. Puede mejorar un archivo por separado y empeorar el conjunto.
Ninguno de esos problemas se detecta comprobando si funciona.
Por eso, meter IA en un proceso de desarrollo no es simplemente pedirle que escriba mejor código.
Su valor real aparece antes y después de escribirlo: cuando ayuda a entender código que nadie documentó, a localizar todo lo que hay que cambiar, a anticipar efectos secundarios y a dejar por escrito por qué se decidió cada cosa.
En Èmfasi tenemos una costumbre sana, o ligeramente temeraria: antes de convertir una idea en recomendación para un cliente, la probamos en nuestros propios proyectos. Nos interesa saber dónde falla el método, no solo dónde luce bien.
Hace poco nos tocó uno que servía perfectamente para eso: migrar una aplicación web de gestión de actividades de PHP 5.3 a PHP 8.4.
Contenidos
Qué significa migrar de PHP 5 a PHP 8
PHP es el lenguaje sobre el que funcionan la mayoría de webs y aplicaciones de gestión. Como cualquier programa, tiene versiones, y las antiguas dejan de recibir actualizaciones de seguridad.
Cuando una aplicación se quedó escrita para PHP 5, tarde o temprano llega el aviso del hosting: esa versión ya no está soportada. A partir de ahí hay dos opciones, actualizar o quedarse con una aplicación cada vez más expuesta y más difícil de mantener.
El problema es que actualizar no es cambiar un desplegable en el panel del servidor.
Entre PHP 5.3 y PHP 8.4 hay catorce años. Cambian funciones que se han eliminado, comportamientos que antes eran de una manera y ahora son de otra, el sistema de avisos y errores, y hasta la forma en que el lenguaje compara dos valores.
En nuestro caso, además, la aplicación funcionaba, la usaba gente cada día y no podía dejar de funcionar durante el proceso.
Podríamos haber abierto el proyecto y haber pedido a la IA que lo modernizara entero. Habríamos obtenido código nuevo rápido, pero habríamos empezado por el final.
Antes de tocar una línea había que resolver cosas más importantes: hasta dónde llegaba el proyecto, qué partes debían quedarse exactamente igual, qué comportamientos podían cambiar sin que nadie lo notara y cómo íbamos a saber, si algo fallaba, de dónde venía el fallo.
La IA estuvo presente todo el proceso, pero no para sustituir esas decisiones. La usamos para entender el punto de partida, ordenar el trabajo y revisar mejor el resultado.
Porque el problema de una migración no es el código que deja de funcionar. Es el que sigue funcionando de otra manera.
Que el código funcione no significa que esté bien
Una IA generativa está hecha para producir una respuesta plausible. En desarrollo, «plausible» tiene una trampa: el código o funciona o no funciona, y cuando funciona parece que la discusión ha terminado.
No ha terminado.
En un proyecto real, un cambio se juzga por cosas que la ejecución no muestra. Si encaja con lo que ya existe. Si respeta las normas del proyecto, aunque sean antiguas. Si alguien podrá entenderlo dentro de un año. Si hace exactamente lo mismo que antes o lo cambia sin avisar.
La IA puede decirte si algo funciona. No puede decirte si encaja.
Eso depende de información que no está en la pregunta que le haces: por qué el código se escribió así, qué se probó y se descartó, qué restricciones tiene el cliente, qué se va a construir después.
Cuando falta ese contexto, la IA rellena los huecos con lo más habitual. Y lo habitual, código moderno con framework y estructura de proyecto actual, no siempre es lo adecuado para la aplicación que tienes delante.
Antes de pedir código, hay que entender lo que ya existe
Qué es la fase 0 de una migración
En algunos proyectos de Èmfasi llamamos fase 0 al trabajo de recopilar y comprobar información antes de empezar. En SEO significa una cosa; en desarrollo, algo bastante parecido.
Antes de tocar nada reunimos el contexto real: qué archivos hay, de qué depende el proyecto y con qué versiones, qué se ejecuta en cada pantalla, qué partes reciben más tráfico, qué servicios externos están conectados, qué se puede probar en local y qué solo existe en el servidor de producción.
En este proyecto la fase 0 dio un resultado incómodo, que es justo para lo que sirve: no había documentación, no había pruebas automáticas y buena parte de la lógica estaba mezclada con el diseño de las pantallas. La persona que lo escribió ya no estaba disponible para preguntarle nada.
Ese, y no la sintaxis, era el problema real de la migración.
El contexto no es una introducción kilométrica antes de una instrucción. Es información seleccionada, ordenada y comprobada.
El inventario de lo que había que cambiar no lo hicimos a mano
Aquí es donde la IA aportó valor desde el primer día, y no escribiendo código.
Una migración de este salto empieza por saber exactamente qué hay que tocar. Parte de ese trabajo lo hacen herramientas de análisis de compatibilidad, que listan las funciones eliminadas y las llamadas obsoletas. Eso no lo hace ni lo tiene que hacer una IA.
Pero el listado de una herramienta te dice dónde está el problema. No te dice qué hacía ese código ni por qué.
Con el proyecto conectado al editor pudimos hacer preguntas que en un código sin documentar cuestan días: qué hace este módulo, dónde se usa esta función, qué pasa si cambio este comportamiento, qué partes dependen de esta tabla. Leer código ajeno y explicarlo es una de las cosas que la IA hace bien de verdad.
En un par de sesiones teníamos un mapa de la aplicación que a mano habría costado semanas.
Ese mapa no era una decisión. Era el material con el que decidir.
Dar acceso al código no es delegar las decisiones
Trabajar con el repositorio accesible cambia mucho la calidad de lo que obtienes. La IA deja de imaginar cómo es el proyecto y puede leerlo.
Pero eso no convierte sus propuestas en recomendaciones automáticas.
Una IA con acceso al código puede detectar que hay tres formas distintas de consultar la base de datos. No puede decidir cuál de las tres debe sobrevivir, ni si merece la pena unificarlas ahora o dentro de un año. Esa decisión depende del presupuesto del cliente, del riesgo de tocar una parte que funciona y de hacia dónde va el proyecto.
Una lista de incompatibilidades no es un plan de migración. Un conector no sustituye un criterio, permite contrastarlo mejor.
Migrar no es reescribir, y esa es la línea que lo ordena todo
Esta fue la decisión que ordenó el proyecto entero, y la tomamos antes de cambiar una línea.
El objetivo era que la aplicación funcionara exactamente igual en PHP 8.4. Mismo comportamiento, mismas pantallas, mismos resultados. No era el momento de mejorar la arquitectura, meter un framework ni reorganizar carpetas.
Puede sonar obvio. En la práctica es la línea más difícil de mantener, y la IA empuja constantemente en la dirección contraria.
Si le pides que actualice un archivo de PHP 5.3, no se limita a arreglar lo que está roto. Te propone reorganizar funciones, separar la lógica del diseño, cambiar cómo se cargan los archivos y montar una capa nueva para hablar con la base de datos. Cada propuesta, por separado, es una buena práctica. Todas juntas, en mitad de una migración y sin pruebas automáticas que las respalden, son una reescritura encubierta.
Cuando cambias el motor y el código a la vez, cualquier fallo puede venir de dos sitios. Y no vas a saber de cuál.
Así que fijamos una regla antes de empezar: en esta fase solo se toca lo que impide funcionar en 8.4. Todo lo demás, aunque fuera feo, se quedaba como estaba. Lo que merecía mejorarse se apuntaba en una lista aparte para una segunda fase, ya con la aplicación estable.
Esa regla la tuvimos que recordar bastantes veces. También a nosotros.
Un proyecto así no se resuelve con un único gran prompt
Podríamos haber pedido en una sola instrucción que analizara el proyecto, corrigiera todas las incompatibilidades y dejara la aplicación lista para 8.4.
Habría sido rápido. También habría resultado difícil saber por qué tomó cada dirección, qué supuestos arrastraba y en qué momento se equivocó.
Preferimos dividir el problema en decisiones más pequeñas.
Primero, el inventario de incompatibilidades. Después, agruparlas por tipo de problema en lugar de por archivo:
- todas las conexiones a la base de datos, escritas con un sistema retirado hace años;
- todas las búsquedas de texto hechas con una sintaxis que PHP 8 ya no reconoce;
- todo el código que creaba objetos a la manera de PHP 4;
- todas las comparaciones de valores en los puntos donde el cambio de criterio de PHP 8 podía alterar el resultado.
Cada grupo se resolvía con el mismo criterio en todo el proyecto, se revisaba y se cerraba antes de pasar al siguiente.
Trabajar por tipo de problema tiene una ventaja clara: revisas una decisión una vez y la aplicas en cincuenta sitios, en lugar de revisar cincuenta decisiones distintas.
No es una lista universal, los grupos dependen de cada proyecto. Lo que sí se traslada es el principio: mantener el problema a un tamaño que se pueda revisar de una sentada.
Cada fase producía una conclusión revisable que alimentaba la siguiente. Si una decisión no se sostenía, se corregía ahí, no cuando ya había veinte archivos construidos encima.
Una IA propone, otra ayuda a cuestionarla
En varios momentos contrastamos el resultado entre modelos distintos. No para organizar un combate ni declarar un ganador, sino para darles papeles diferentes.
Uno proponía los cambios de un grupo. El segundo los recibía sin el historial de la conversación y actuaba como revisor crítico: qué comportamiento ha cambiado aquí, qué caso no se ha contemplado, qué parte es más complicada de lo que el problema pedía, qué dependencia nueva no hacía falta.
Después devolvíamos esa crítica al primero para replantear.
Una IA puede ayudarnos a construir una propuesta. Otra puede ayudarnos a desconfiar de ella.
Ese desacuerdo es útil porque rompe la inercia. Cuando llevas veinte mensajes trabajando sobre una misma solución, tanto el equipo como el modelo empiezan a dar por buenas las decisiones anteriores solo porque ya están ahí. Meter otra revisión obliga a volver a justificarlas.
Pero conviene no romantizar el método.
Dos modelos pueden coincidir y estar equivocados. Pueden discrepar por razones poco relevantes o proponer cambios que mejoran un archivo y empeoran el conjunto. La revisión cruzada amplía el análisis, no dicta un veredicto.
La decisión final seguía siendo nuestra.
Los errores que no dan error: el riesgo real de actualizar PHP
La parte visible de una migración así es la que rompe. El código que ya no existe en PHP 8 se detecta solo: la aplicación deja de arrancar y sabes exactamente dónde mirar.
Esa parte, con herramientas y una IA que entiende el proyecto, avanza razonablemente rápido.
Lo que cuesta de verdad es lo otro: el código que sigue funcionando y ahora se comporta de otra manera.
PHP 8 cambió la forma en que compara un texto con un número. Durante años, comparar un texto con un cero daba verdadero. Ahora da falso. Es un cambio correcto y llevaba tiempo pidiéndose, pero en una aplicación con catorce años encima significa que hay filtros, condiciones y validaciones que hacen algo distinto de lo que hacían ayer.
No lanzan ningún error. Simplemente devuelven otra cosa.
Traducido a lo que ve el cliente: un listado que muestra registros de más, un filtro que deja fuera resultados que deberían aparecer, un formulario que acepta algo que antes rechazaba. Nada se cae. Todo parece normal hasta que alguien mira los números y no cuadran.
Y ahí la IA es una ayuda relativa. Puede señalarte todos los sitios donde hay una comparación de ese tipo, y son muchos. Lo que no puede decirte es cuál de ellos importa, porque eso depende de qué datos llegan realmente a cada punto de la aplicación. La IA no sabe que ese campo siempre viene de un desplegable con valores controlados, ni que ese otro se rellena desde un formulario público donde entra cualquier cosa.
Eso lo sabe quien conoce la aplicación, o lo averigua mirando los datos.
El tiempo que ahorras generando lo inviertes revisando. La ganancia está en que revisar sale más barato que escribir desde cero, no en que la revisión desaparezca.
Algo parecido pasó con los avisos que en PHP 8 pasaron a ser errores. Código que durante años había convivido con avisos silenciados empezó a comportarse de otra forma. Ninguna herramienta te dice si ese aviso era irrelevante o si tapaba un problema desde el principio.
Los errores más caros son los que parecen buenas prácticas
La IA tiene una inclinación natural a proponer, ampliar y completar. Si le pides alternativas, rara vez responde: «En realidad, aquí no hace falta tocar nada».
El criterio profesional trabaja muchas veces en la dirección contraria.
En esta migración decidimos no meter un framework, aunque cada revisión lo sugería de alguna forma. No estaba en el objetivo y multiplicaba el riesgo. No reorganizamos la estructura de archivos: es antigua y no la habríamos hecho así, pero moverla nos habría dejado sin poder comparar el antes y el después. No añadimos comprobaciones estrictas de tipos de forma general, porque en un código sin pruebas automáticas esa es una manera muy eficaz de descubrir en producción qué valores llegaban de verdad a cada función. Y no reescribimos los módulos más antiguos, precisamente los que más ganas dan de reescribir: funcionaban, casi nadie los tocaba y no era su turno.
Durante el proceso rechazamos propuestas bien argumentadas que mejoraban un archivo concreto y empeoraban lo que de verdad importaba: poder saber, si algo fallaba, si el fallo venía de la versión de PHP o de nuestros cambios.
Una propuesta no se volvía adecuada por estar bien escrita.
Limitar, aplazar y dejar cosas como están también son decisiones técnicas.
Poder generar veinte enfoques en segundos no elimina la necesidad de elegir uno. Solo hace más visible la responsabilidad de hacerlo.
Documentar la migración no es guardar conversaciones
Todo el proceso se recogió en un documento de migración.
Incluía qué se cambió en cada grupo y con qué criterio, qué comportamientos podían haber cambiado y dónde vigilarlos, qué decidimos no tocar y por qué, y la lista de mejoras aplazadas a una segunda fase.
Eso es muy distinto de conservar un historial de chat.
Una conversación puede contener ideas valiosas, pero también preguntas provisionales, caminos abandonados, respuestas contradictorias y mucho material que solo tenía sentido en el momento en que se produjo.
Buscar meses después la decisión importante entre decenas de mensajes es una forma poco sofisticada de arqueología digital.
La documentación convierte el intercambio en memoria de proyecto.
En una migración esto tiene un valor evidente. Cuando algo falle dentro de tres meses, la primera pregunta será si tiene que ver con el cambio de versión. Con ese documento delante, se responde en diez minutos en lugar de en dos días.
El código dice lo que hace. Casi nunca dice por qué se hizo así en lugar de la otra forma, que era la que parecía obvia.
Qué significa para nosotros ser una agencia AI First
No consiste en generar más rápido, usar todas las herramientas disponibles o automatizar cualquier tarea que admita una instrucción.
Tampoco en aceptar la primera respuesta porque llega en diez segundos y arranca.
En esta migración la IA nos ahorró la parte más lenta y menos interesante: entender un código sin documentar, localizar todo lo que había que cambiar y aplicar el mismo criterio en decenas de sitios sin saltarnos ninguno. Eso es mucho.
Lo que no hizo fue decidir hasta dónde llegaba el proyecto, qué se quedaba como estaba y qué riesgos podíamos asumir con una aplicación en uso. Esas decisiones eran las que determinaban si la migración salía bien.
El criterio profesional sigue definiendo el alcance, interpretando las restricciones, estableciendo prioridades y respondiendo de lo que se despliega.
Porque cuando algo se rompe en producción a las once de la noche, no hay ningún modelo al que reclamarle nada.
No usamos la IA para dejar de pensar. La usamos para pensar con más información, más orden y más capacidad crítica.
Esta forma de trabajar no se limita al desarrollo. También la aplicamos en procesos como la IA aplicada al SEO o el diseño UX/UI asistido por inteligencia artificial, donde generar opciones tampoco sustituye la necesidad de decidir con criterio.
Preguntas frecuentes sobre migrar de PHP 5 a PHP 8 con IA
¿Se puede migrar una aplicación de PHP 5.3 a 8.4 con IA?
La IA ayuda mucho en la parte de entender el código, localizar todas las incompatibilidades y aplicar el mismo criterio en muchos archivos sin saltarse ninguno. Lo que no resuelve es el alcance del proyecto: hasta dónde llegar, qué dejar como está y qué riesgos se pueden asumir con una aplicación en uso. Esas decisiones siguen siendo del equipo técnico.
¿Qué es lo que la IA no detecta al migrar código antiguo?
Los cambios de comportamiento que no producen ningún error. PHP 8 modificó, por ejemplo, la forma en que se comparan una cadena de texto y un número: código que funcionaba sigue ejecutándose, pero devuelve otro resultado. La IA puede señalar dónde están esas comparaciones, pero no qué datos llegan realmente a cada punto de la aplicación.
¿Conviene aprovechar la migración para modernizar el código?
En general, no a la vez. Si cambias la versión de PHP y la arquitectura en el mismo movimiento, cualquier fallo posterior puede venir de dos sitios y no sabrás de cuál. Es más seguro migrar primero manteniendo el comportamiento, y dejar las mejoras para una segunda fase con la aplicación ya estable.
¿Hace falta tener tests antes de migrar?
Ayuda mucho, pero es habitual que un proyecto antiguo no los tenga. Cuando no existen, el sustituto razonable es limitar al máximo los cambios, trabajar por grupos de problemas para poder revisar cada decisión una sola vez y documentar qué comportamientos pueden haber cambiado y dónde vigilarlos.
¿Cuánto tiempo ahorra realmente la IA en una migración?
Ahorra sobre todo en comprensión: entender un código sin documentar y saber qué hay que cambiar es lo que más tiempo consume, y ahí la diferencia es grande. En cambio, el tiempo que ahorras generando lo inviertes revisando. La ganancia está en que revisar es más barato que escribir desde cero, no en que la revisión desaparezca.
¿Qué herramientas hacen falta además de la IA?
Un análisis de compatibilidad que liste funciones eliminadas y llamadas obsoletas, control de versiones para poder comparar el antes y el después, y un entorno donde probar sin tocar producción. La IA se apoya en esa información; no la sustituye.