Saltar al contenido
DedicatedPHP Contactar

Cómo actualizar PHP sin convertir el cambio en una reescritura

Una guía para inventariar dependencias, detectar incompatibilidades, validar en CI y desplegar una actualización de PHP con criterios claros de reversión.

Diagrama de planificación de una actualización de PHP con dependencias, pruebas y reversión

Actualizar la versión de PHP en una aplicación existente no consiste únicamente en cambiar la imagen del contenedor o la configuración del servidor. El runtime interactúa con el código, las extensiones, las bibliotecas de Composer y los procesos que ejecutan tareas programadas o trabajos en segundo plano. Un cambio puede afectar a cualquiera de esas piezas, incluso aunque la aplicación parezca funcionar con normalidad durante una prueba manual.

La forma de reducir incertidumbre es tratar la actualización como un cambio de compatibilidad: inventariar qué se ejecuta, buscar incompatibilidades, validar rutas representativas y definir por adelantado cómo decidir si el despliegue continúa o se revierte. El objetivo es aislar el trabajo necesario para el nuevo runtime, no convertir la actualización en una reescritura del producto.

El runtime es parte de la compatibilidad de la aplicación

El runtime es parte de la compatibilidad de la aplicación — guía visual de DedicatedPHP

Una versión de PHP determina qué sintaxis admite el intérprete y cómo se comportan determinadas funciones y tipos. También establece qué versiones de extensiones y dependencias pueden instalarse. Por eso, que el código haya funcionado en el entorno actual no demuestra que vaya a funcionar en el nuevo: podrían cambiar una función, una interfaz, un comportamiento de tipos o la disponibilidad de una extensión.

Conviene distinguir tres ámbitos: el código de la aplicación, las dependencias de terceros y la configuración del entorno. Si se modifican los tres a la vez, un fallo resulta más difícil de atribuir. Una actualización planificada separa esos cambios siempre que sea viable y mantiene explícito qué componente introdujo cada ajuste.

Inventaría el runtime, las dependencias y los procesos

Antes de cambiar nada, registra el entorno real de ejecución, no solo el que describe el archivo de configuración del proyecto. Comprueba la versión de PHP en los contenedores o servidores que atienden solicitudes y en los que ejecutan tareas programadas, consumidores de colas y comandos de mantenimiento. Esos procesos pueden usar imágenes, variables o extensiones distintas.

  • Runtime y extensiones: identifica las extensiones habilitadas, sus versiones cuando corresponda y las bibliotecas del sistema de las que dependen. Compara los requisitos de producción, CI y desarrollo.
  • Dependencias Composer: revisa composer.json, el archivo de bloqueo y las restricciones de PHP declaradas por los paquetes. Comprueba también herramientas de desarrollo, como analizadores y runners de pruebas.
  • Configuración: inventaría valores de php.ini, límites de memoria y tiempo, configuración de errores y ajustes específicos del servidor. Un runtime nuevo no garantiza que se hayan conservado los parámetros relevantes.
  • Trabajo fuera de las solicitudes web: incluye cron, colas, comandos de consola, importaciones, exportaciones y tareas de larga duración. Una ruta web correcta no valida automáticamente esos flujos.
  • Integraciones y datos: anota servicios externos, formatos intercambiados y escrituras en bases de datos o almacenamiento. Esto ayuda a identificar qué operaciones requieren atención especial durante una reversión.

El inventario puede ser una lista mantenida en el repositorio o en la documentación de operación, siempre que permita comparar los entornos y detectar discrepancias. Un síntoma frecuente de un inventario incompleto es que CI pasa, pero un worker o una tarea programada falla después del despliegue.

Busca incompatibilidades con varias señales

Empieza por las herramientas automatizadas: revisa las restricciones de plataforma de Composer y ejecuta una comprobación de dependencias con la versión de PHP objetivo. Un conflicto de resolución indica que algún paquete, incluidas las herramientas de desarrollo, no declara compatibilidad con esa plataforma. No conviene forzar la instalación para ocultar el conflicto sin entender qué requisito se está eludiendo.

Complementa ese análisis con herramientas de análisis estático y pruebas de estilo o de compatibilidad disponibles en el proyecto. Pueden señalar usos sospechosos, APIs obsoletas o patrones que merecen revisión, pero no demuestran por sí solas que toda la aplicación funcione. Del mismo modo, un análisis sin incidencias no sustituye la ejecución real: algunos errores aparecen solo al recorrer una rama poco habitual o al cargar una extensión.

Ejecuta las pruebas con el runtime objetivo y las extensiones que se esperan en producción. Si la suite es limitada, añade comprobaciones manuales o automatizadas de los flujos con mayor impacto: autenticación, operaciones de escritura, cobros si los hubiera, generación de documentos e integraciones esenciales. Captura también errores y advertencias; un cambio que convierte una advertencia en una excepción puede interrumpir una ruta antes de que la suite lo detecte.

Ordena el trabajo para aislar el riesgo

Una secuencia práctica es empezar por confirmar la imagen o configuración candidata y sus extensiones, después resolver las restricciones de dependencias y, por último, corregir el código y los ajustes que impidan ejecutar las pruebas. Mantén cada grupo de cambios revisable. Si una biblioteca necesita actualizarse, documenta qué requisito obliga al cambio y prueba sus áreas de uso en la aplicación.

Evita actualizar indiscriminadamente todas las dependencias como parte del mismo paso. Una actualización amplia puede ser necesaria, pero aumenta el número de causas posibles si aparece una regresión. Si no puede separarse, registra qué paquetes cambiaron y añade pruebas dirigidas a las funcionalidades que dependen de ellos. Asegúrate también de que el archivo de bloqueo se genera y se instala de forma consistente entre CI y producción.

La configuración debe reflejar el destino real. Validar con una extensión instalada solo en CI produce una señal engañosa; lo mismo ocurre si las tareas de fondo siguen ejecutándose con el runtime anterior. Compara las imágenes, comandos de arranque, variables y configuración entre el entorno de pruebas y el de producción antes de atribuir un resultado al código.

Valida en un entorno representativo y define la salida

CI debe ejecutar instalación, análisis y pruebas con el runtime objetivo, no únicamente con el actual. Añade trabajos separados para otros runtimes solo si la aplicación debe mantener una ventana de compatibilidad: en ese caso, cada combinación admitida necesita comprobación explícita. Una matriz de CI puede mostrar qué combinaciones se prueban, pero no cubre automáticamente las particularidades de producción.

Usa un entorno de preproducción suficientemente parecido al real para comprobar arranque, rutas críticas, integraciones, colas y tareas programadas. Revisa registros, errores, tiempos de respuesta y consumo de recursos antes y después. Define de antemano qué comportamiento detendría el despliegue, quién toma esa decisión y durante cuánto tiempo se observará el sistema. Los umbrales deben basarse en las necesidades y señales disponibles para la aplicación, no en valores genéricos.

Un criterio de salida útil incluye: instalación reproducible, suite acordada en verde, flujos críticos verificados, ausencia de errores nuevos no explicados y capacidad de operar los procesos de fondo. Registra excepciones conocidas y su propietario. “Las pruebas pasan” es insuficiente si el conjunto no cubre una integración esencial o si el equipo desconoce qué métrica debe vigilar.

Despliega con una reversión compatible con los datos

Si la arquitectura y la plataforma lo permiten, expón el runtime nuevo de forma gradual: primero en un entorno controlado y luego a una parte del tráfico o de la capacidad de ejecución. La exposición gradual es una estrategia de despliegue, no una divulgación de información. No siempre es posible repartir solicitudes entre versiones —por ejemplo, si hay procesos con estado o diferencias en el protocolo interno—; en ese caso, planifica una transición coordinada y comprueba explícitamente los consumidores y productores de mensajes.

Antes de desplegar, verifica que el código anterior puede volver a ejecutarse en caso de fallo. La reversión no consiste solo en restaurar una imagen: una migración de base de datos, un formato nuevo de mensaje o una escritura incompatible puede impedir que el runtime anterior lea los datos creados por el nuevo. Prefiere cambios de esquema compatibles por etapas: ampliar primero, desplegar código capaz de convivir con ambas formas y retirar lo antiguo cuando ya no haya consumidores que lo necesiten. Para cada paso irreversible, define una recuperación específica y una decisión de parada.

Durante el despliegue, vigila errores de aplicación y del runtime, fallos de workers, retraso de colas, tareas programadas y señales de negocio relevantes. Si se activa un criterio de reversión, detén la expansión del cambio y sigue el procedimiento probado. Conserva los registros necesarios para determinar la causa; revertir sin diagnosticar puede hacer que el mismo fallo reaparezca en el siguiente intento.

Lista de comprobación para decidir si está preparada

Lista de comprobación para decidir si está preparada — guía visual de DedicatedPHP
  • ¿Están identificados el runtime y las extensiones de todos los entornos y procesos?
  • ¿Se han revisado las restricciones de Composer y las herramientas de desarrollo?
  • ¿Se ejecutan análisis y pruebas con la configuración objetivo?
  • ¿Se han probado rutas críticas, integraciones, colas y tareas programadas?
  • ¿Se conocen las diferencias entre CI, preproducción y producción?
  • ¿Hay señales operativas, responsables y criterios claros para continuar o detener?
  • ¿El código anterior puede trabajar con los datos y mensajes que producirá el nuevo?
  • ¿Se ha ensayado la reversión y se sabe qué cambios no pueden deshacerse automáticamente?

La decisión de actualizar la versión de PHP en una aplicación existente es más sólida cuando el equipo puede responder a esas preguntas con evidencia. Si faltan pruebas o inventario, el siguiente paso no tiene por qué ser una reescritura: puede consistir en cerrar primero esas brechas y reducir el tamaño del cambio. Así, los fallos potenciales se detectan antes de afectar a usuarios y cada decisión de despliegue tiene un criterio verificable.

¿Quieres aplicar estas ideas a tu proyecto?Hablemos de tu plataforma PHP.
Ver servicio relacionado