PHP 8.4 y 8.5: qué cambia y cómo migrar sin dolor (y prepararse para PHP 9)

Migrar PHP 8 a 8.4 y 8.5: qué cambia y cómo hacerlo sin dolor

Si tu plataforma sigue corriendo sobre PHP 8.1 o anterior, ya estás en una versión sin soporte: PHP 8.1 dejó de recibir parches de seguridad el 31 de diciembre de 2025, y PHP 8.2 entra en su último año de mantenimiento en 2026. Mientras tanto, PHP 8.4 (noviembre de 2024) y PHP 8.5 (noviembre de 2025) han cambiado más el lenguaje que cualquier otra pareja de versiones desde el salto a PHP 7, y el proyecto ya está limpiando el terreno para PHP 9, la versión que convertirá en errores fatales todo lo que hoy solo es un aviso de «deprecated» en tus logs.

Para un CTO o responsable de IT, migrar PHP 8 a su última versión no es un capricho de desarrolladores: es una cuestión de seguridad (las CVE de PHP no se corrigen en ramas muertas), de rendimiento (cada versión mayor recorta tiempos de respuesta y consumo de CPU sin tocar una línea de código) y de compatibilidad con el ecosistema, porque WordPress, Laravel, Symfony, PrestaShop o Drupal suben el mínimo exigido cada pocos meses y llegará el día en que no puedas actualizar un plugin crítico porque tu servidor se quedó atrás.

En esta guía repasamos qué cambia de verdad en PHP 8.4 y 8.5, qué se sabe hoy de PHP 9, qué rupturas arrastras si vienes de 7.4 u 8.0, cómo está cada CMS y framework respecto a las nuevas versiones, y sobre todo un método de migración paso a paso —inventario, análisis estático, corrección automatizada con Rector, staging, despliegue progresivo y vuelta atrás— que hemos aplicado en tiendas online, intranets y aplicaciones a medida con cientos de miles de líneas de código heredado. El objetivo es que la migración sea un proyecto acotado y predecible, no una semana de incendios.

1. Calendario de soporte: dónde está tu versión hoy

Lo primero es situarse. Cada versión de PHP tiene dos años de soporte activo (correcciones de errores y seguridad) y, desde PHP 8.1, dos años más de soporte solo de seguridad. Cuando esa ventana se cierra, cualquier vulnerabilidad descubierta después se queda sin parche oficial, y tu única red de seguridad pasa a ser el WAF o los backports que haga tu distribución Linux —si los hace—.

Versión Lanzamiento Fin soporte activo Fin soporte seguridad Estado (sep. 2026)
PHP 7.4 y anteriores 2019 2021 28-11-2022 Sin soporte desde hace años
PHP 8.0 nov. 2020 nov. 2022 26-11-2023 Sin soporte
PHP 8.1 nov. 2021 nov. 2023 31-12-2025 Sin soporte
PHP 8.2 dic. 2022 31-12-2024 31-12-2026 Solo seguridad, caduca en meses
PHP 8.3 nov. 2023 31-12-2025 31-12-2027 Solo seguridad
PHP 8.4 nov. 2024 31-12-2026 31-12-2028 Activo
PHP 8.5 nov. 2025 31-12-2027 31-12-2029 Activo (última estable)

Dos lecturas rápidas de la tabla. La primera: si hoy estás en 8.1 o menos, la migración es urgente y el objetivo debería ser 8.4 como mínimo, idealmente 8.5. La segunda: si estás en 8.2 o 8.3, tienes margen pero no mucho; conviene planificar el salto a 8.4/8.5 dentro de 2026 para no repetir el ciclo de urgencia dentro de un año. Y ojo con el «estoy en Ubuntu LTS, ya me lo parchean ellos»: Canonical y Red Hat hacen backports de seguridad de la versión que empaquetan, pero no de todas las CVE ni indefinidamente, y las versiones nuevas de tus frameworks no van a esperar.

Calendario de soporte de PHP 8.1 a 8.5 para planificar migrar PHP 8 a su última versión
Ventanas de soporte de las ramas de PHP 8: en 2026 solo 8.4 y 8.5 reciben correcciones de errores; 8.2 cierra el año sin ningún soporte.

2. Qué cambia en PHP 8.4

PHP 8.4 es la versión que más ha modernizado la sintaxis de clases desde las propiedades tipadas de 7.4. Estas son las novedades con impacto real en código de empresa.

2.1 Property hooks: adiós a los getters y setters de relleno

Los property hooks permiten definir lógica de lectura y escritura directamente en la propiedad, sin métodos getX()/setX() ni magia con __get/__set. Es el cambio que más va a afectar a cómo se escriben entidades, DTOs y value objects:

class Pedido
{
    public string $referencia {
        set (string $valor) {
            if (!preg_match('/^PED-\d{6}$/', $valor)) {
                throw new InvalidArgumentException("Referencia inválida: $valor");
            }
            $this->referencia = strtoupper($valor);
        }
    }

    public float $totalConIva {
        get => round($this->base * (1 + $this->iva), 2);
    }

    public function __construct(private float $base, private float $iva) {}
}

Los hooks también funcionan en interfaces, lo que permite declarar «esta interfaz expone una propiedad $id de solo lectura» sin obligar a implementar un método. Para equipos que mantienen frameworks internos o librerías de dominio, esto elimina cientos de líneas de boilerplate.

2.2 Visibilidad asimétrica

Ahora una propiedad puede ser pública para leer y privada para escribir: public private(set) int $intentos = 0;. Combinado con readonly y con los hooks, cubre el 90% de los casos en los que antes se encapsulaba una propiedad detrás de un getter solo para impedir que alguien la modificara desde fuera.

2.3 Nueva API DOM y parser HTML5

La extensión DOM estrena las clases Dom\HTMLDocument y Dom\XMLDocument, con un parser HTML5 conforme al estándar (el antiguo DOMDocument::loadHTML se basa en libxml2 y en HTML4, y «rompe» muchas páginas modernas). Si tu aplicación hace scraping, genera PDFs a partir de HTML, limpia contenido de usuarios o integra feeds de proveedores, esta API resuelve una fuente histórica de bugs raros con etiquetas mal cerradas y <template>.

2.4 Funciones nuevas y ergonomía

  • array_find(), array_find_key(), array_any() y array_all(): por fin sin escribir bucles ni array_filter + reset para buscar el primer elemento que cumple una condición.
  • new sin paréntesis: new Cliente()->activar() ya es válido sin envolver en (new Cliente()).
  • Objetos perezosos (lazy objects): la API ReflectionClass::newLazyGhost()/newLazyProxy() permite que ORMs y contenedores de dependencias creen objetos cuya inicialización se difiere hasta el primer uso, sin generar clases proxy en tiempo de compilación. Doctrine y Symfony ya lo aprovechan.
  • mb_trim(), mb_ltrim(), mb_rtrim(), mb_ucfirst(): versiones multibyte que faltaban desde hace 15 años.
  • Atributo #[\Deprecated]: ahora tú puedes marcar métodos de tu propio código como obsoletos y PHP emitirá el aviso, igual que hace con las funciones internas.
  • BCMath orientado a objetos (BcMath\Number) con operadores sobrecargados, útil en facturación y cálculo de precios con precisión arbitraria.
  • Cambios en round() y nuevos modos de redondeo (RoundingMode como enum). Si tu ecommerce redondea precios «a mano», revisa que el comportamiento no cambie en los límites.

2.5 Deprecaciones y rupturas de PHP 8.4

  • Tipos nulables implícitos: function f(Foo $x = null) está deprecado; debe escribirse ?Foo $x = null. Es la deprecación que más ruido genera en código antiguo y en plugins de WordPress. Rector la corrige en segundos.
  • Extensiones que salen del núcleo: IMAP, PSpell, OCI8 y PDO_OCI pasan a PECL. Si tu aplicación lee buzones IMAP (típico en helpdesks y en integraciones de pedidos por email), tendrás que instalar la extensión aparte o migrar a una librería como webklex/php-imap.
  • Sesiones y cookies: session.sid_length y session.sid_bits_per_character quedan deprecados; el algoritmo por defecto ya es seguro, pero si los fijabas en php.ini verás avisos.
  • Constantes E_STRICT y varias funciones de mysqli y xml heredadas quedan marcadas como obsoletas.
  • exit y die pasan a comportarse como funciones: cambio interno que solo afecta a código que hacía cosas extrañas con ellas.

3. Qué trae PHP 8.5

PHP 8.5, publicado en noviembre de 2025, es más pequeño que 8.4 en cuanto a sintaxis pero introduce dos construcciones que van a cambiar el estilo del código en los próximos años, además de mejorar la depuración en producción.

3.1 El operador pipe |>

Permite encadenar llamadas pasando el resultado de una expresión como primer argumento de la siguiente, evitando el clásico anidamiento de funciones ilegible:

// Antes
$slug = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $titulo), '-'));

// PHP 8.5
$slug = $titulo
    |> fn($s) => preg_replace('/[^A-Za-z0-9-]+/', '-', $s)
    |> fn($s) => trim($s, '-')
    |> strtolower(...);

3.2 clone with y objetos inmutables

Clonar un objeto readonly modificando una o varias propiedades en la misma operación —clone($pedido, ['estado' => 'enviado'])— era imposible sin trucos. Ahora es una construcción del lenguaje, lo que hace viables los value objects inmutables sin escribir un método withX() por propiedad.

3.3 Otras novedades destacables de 8.5

  • Extensión uri integrada, con parsers conformes a RFC 3986 y al estándar WHATWG. Sustituye al infame parse_url(), que devuelve resultados distintos según la forma de la URL y ha originado más de un fallo de seguridad en validaciones de redirecciones.
  • array_first() y array_last(): complementan a array_key_first()/array_key_last().
  • Atributo #[\NoDiscard]: avisa cuando se ignora el valor devuelto por una función, ideal para métodos que devuelven un objeto nuevo en lugar de mutar (por ejemplo, los with*() de PSR-7).
  • Trazas en errores fatales (fatal_error_backtraces): por primera vez un «Allowed memory size exhausted» o un timeout muestra la pila de llamadas en el log. Para quien opera aplicaciones en producción es, posiblemente, la mejora más útil de la versión.
  • php --ini=diff: muestra solo las directivas que difieren del valor por defecto. Un ahorro enorme al auditar servidores heredados.
  • Closures estáticos en expresiones constantes y constantes finales en interfaces.
  • Deprecaciones: los tipos de cast no canónicos ((integer), (boolean), (double)), el operador de ejecución con comillas invertidas (`ls`), __sleep()/__wakeup() a favor de __serialize()/__unserialize(), y varias funciones de mhash y SplFixedArray.

4. PHP 9: lo que sabemos y lo que conviene preparar ya

A fecha de septiembre de 2026 PHP 9 no tiene fecha oficial de publicación: el equipo del lenguaje ha dejado claro que llegará cuando haya suficientes cambios incompatibles acumulados que justifiquen un salto de versión mayor, y no antes. Lo que sí sabemos con certeza es qué va a pasar en ese momento, porque la política del proyecto es explícita: todo lo deprecado en la rama 8.x se elimina o se convierte en error en 9.0. Eso incluye, entre lo más relevante para código de empresa:

  • Propiedades dinámicas (deprecadas en 8.2): crear $obj->propiedadNueva = 1 sin declararla ni usar #[\AllowDynamicProperties] lanzará un Error. En aplicaciones heredadas es, de lejos, la mayor fuente de trabajo.
  • Interpolación ${var} en cadenas (deprecada en 8.2): solo sobrevivirá la sintaxis {$var}.
  • Pasar null a parámetros no nulables de funciones internas (deprecado en 8.1): strlen(null), htmlspecialchars(null), trim(null)… habituales en plantillas y en código que confía en que «algo» llegará vacío en lugar de nulo. Esto será un TypeError.
  • Tipos nulables implícitos (8.4), casts no canónicos y backticks (8.5).
  • Retorno implícito de float a int con pérdida de precisión y conversiones de cadena numérica no estricta, ya avisadas desde 8.1.
  • Funciones eliminadas hace tiempo del roadmap: utf8_encode()/utf8_decode() (deprecadas en 8.2), la extensión mcrypt (fuera desde 7.2), each(), create_function()…

Lo importante es el enfoque: PHP 9 no será una migración distinta, será la factura de las deprecaciones que hayas ignorado. Si al llegar a 8.5 tu log de producción está limpio de E_DEPRECATED, el salto a 9 será trivial. Si no lo está, cada aviso de hoy es un fatal error de mañana. Por eso el método que proponemos más abajo trata las deprecaciones como errores desde el primer día.

5. Si vienes de PHP 7.4 u 8.0: las rupturas acumuladas

Muchas de las aplicaciones que auditamos siguen en 7.4 (o incluso 7.2) porque «funciona». Al migrar a 8.4/8.5 no te enfrentas a los cambios de una versión, sino a los de cinco. Esta es la lista corta de lo que realmente rompe, ordenada por frecuencia en proyectos reales:

Versión Ruptura Síntoma típico
8.0 Comparación cadena-número saneada (0 == "abc" ahora es false) Condiciones que antes entraban y ahora no, sin error alguno
8.0 Muchos avisos internos pasan a TypeError/ValueError Pantallas en blanco donde antes había un warning silencioso
8.0 Precedencia de concatenación y suma cambiada; match y argumentos con nombre nuevos Cálculos de importes con resultado distinto
8.1 Null a parámetros internos no nulables deprecado; acceso a $GLOBALS restringido Logs llenos de Passing null to parameter #1
8.1 Métodos de interfaces internas (ArrayAccess, Countable, Iterator) exigen tipos de retorno o #[\ReturnTypeWillChange] Avisos en librerías antiguas que no se actualizan
8.2 Propiedades dinámicas deprecadas; ${} deprecado; utf8_encode deprecada Miles de avisos en código procedural y en plugins
8.3 Constantes de clase tipadas; unserialize() más estricto; cambios en range() Sesiones y cachés serializadas que dejan de cargar
8.4 Nulables implícitos deprecados; IMAP/PSpell/OCI8 fuera del núcleo; round() ajustado «Class IMAP not found» en el servidor nuevo
8.5 Casts no canónicos, backticks y __sleep/__wakeup deprecados Avisos en scripts de sistema y en librerías de serialización

La mayor parte de estas rupturas no aparece en el análisis estático porque dependen de datos: la comparación laxa de 8.0 o el null a strlen() solo saltan cuando llega el pedido raro, el cliente sin apellido o el producto con precio vacío. De ahí la importancia de probar con datos reales anonimizados y de registrar las deprecaciones en producción durante semanas, como veremos en el método.

6. Compatibilidad del ecosistema: CMS, frameworks y extensiones

La versión de PHP que puedes usar la marca el eslabón más débil de tu stack. Antes de decidir el objetivo (8.4 u 8.5), comprueba estos tres frentes.

6.1 CMS y plataformas de ecommerce

  • WordPress: el núcleo de WordPress 6.8+ y 7.x funciona sobre PHP 8.4 y el proyecto va cerrando progresivamente los avisos de 8.5. El problema nunca es el core, sino los plugins y temas: en una instalación media con 30-40 plugins, siempre hay dos o tres abandonados que rompen. Si vas a subir de versión de PHP, aprovecha para revisar la guía de actualización a WordPress 7 y hacer las dos cosas en un mismo ciclo de pruebas.
  • WooCommerce: sigue la política de WordPress y declara compatibilidad probada con 8.4; las extensiones de pago, envío y ERP son el punto a vigilar.
  • PrestaShop: PrestaShop 8.x soporta hasta PHP 8.1 (8.2 con parches en las últimas 8.2.x); PrestaShop 9 es la rama que soporta PHP 8.1 a 8.4. Si estás en 1.7 con PHP 7.4, la ruta pasa obligatoriamente por migrar de PrestaShop 1.7 a PrestaShop 9, y con ella los módulos de terceros.
  • Drupal: Drupal 11 exige PHP 8.3 como mínimo y funciona sobre 8.4; Drupal 10.x cubre 8.1-8.4. Las instalaciones en Drupal 7 son el caso más crítico: Drupal 7 no tiene soporte y sus módulos no están preparados para PHP 8, así que hay que abordar la migración de Drupal 7 a Drupal 11 como proyecto completo.
  • Magento / Adobe Commerce: 2.4.7 y 2.4.8 soportan PHP 8.3 y 8.4 respectivamente; versiones anteriores están ancladas a 8.1/8.2.

6.2 Frameworks y librerías

  • Laravel 11 y 12 requieren PHP 8.2+ y están probados con 8.4; Laravel 12 ya se ejecuta sin avisos en 8.5.
  • Symfony 7.x requiere 8.2+ y es de los primeros en aprovechar los objetos perezosos y los hooks de 8.4.
  • Doctrine ORM 3, PHPUnit 11/12, Guzzle 7, Monolog 3: todos en 8.4; lo que suele fallar son las dependencias transitivas antiguas (un phpmailer de 2017, una librería de PDF sin mantenimiento, un SDK de transportista escrito para PHP 5.6).
  • SuiteCRM 8 se apoya en Symfony y va subiendo el mínimo de PHP con cada 8.x; SuiteCRM 7 sigue anclado a versiones antiguas de PHP, un motivo más para planificar su migración.

6.3 Extensiones de PHP y servidor

Comprueba que el hosting o la imagen Docker de destino tiene compiladas todas las extensiones que usas (php -m en origen y destino, y compara). Las víctimas habituales son imap (fuera del núcleo en 8.4), gd con soporte WebP/AVIF, intl, soap, bcmath, sodium y los conectores de bases de datos exóticas. Y no olvides opcache con la configuración adecuada: una migración es el momento perfecto para optimizar PHP-FPM y php.ini, porque cada versión trae nuevos valores por defecto y opciones de JIT.

7. Método de migración paso a paso

Este es el proceso que aplicamos en Keliam, ajustando el tamaño de cada fase al del proyecto. En una aplicación media (100-200k líneas, 40-60 dependencias) el ciclo completo son entre dos y cuatro semanas de trabajo real, la mayor parte en pruebas.

Ruta en seis pasos para migrar PHP 8 a 8.4 o 8.5: inventario, análisis estático, Rector, pruebas, despliegue progresivo y limpieza de deprecaciones
Las seis fases de una migración de versión de PHP sin sobresaltos: el trabajo pesado está en el análisis previo y en las pruebas, no en el cambio de servidor.

7.1 Inventario: qué tienes y quién lo bloquea

Empieza por un inventario honesto: versión actual de PHP en cada entorno, extensiones cargadas, lista de dependencias Composer con su versión y estado de mantenimiento, y código propio fuera de Composer (plugins a medida, scripts cron, integraciones). Composer te dice en segundos qué paquete impide subir de versión:

# Qué paquetes no permiten PHP 8.4
composer why-not php 8.4

# Simular la plataforma de destino sin cambiar el binario local
composer config platform.php 8.4.0
composer update --dry-run

# Extensiones activas (ejecutar en origen y en destino, comparar)
php -m | sort > ext-$(php -r 'echo PHP_VERSION;').txt

Cada paquete bloqueante tiene tres salidas: actualizarlo (lo normal), sustituirlo por una alternativa mantenida, o hacer un fork mínimo si es crítico y está abandonado. Documenta la decisión para cada uno; es la parte del proyecto en la que se esconde el riesgo, y también la que más deuda técnica saca a la luz.

7.2 Análisis estático: PHPCompatibility, PHPStan y Rector en modo lectura

Con el inventario hecho, pasa el código propio por tres herramientas complementarias:

  • PHPCompatibility (reglas para PHP_CodeSniffer) detecta funciones eliminadas, sintaxis obsoleta y extensiones retiradas contra una versión objetivo concreta: phpcs -p . --standard=PHPCompatibility --runtime-set testVersion 8.4.
  • PHPStan con la extensión de deprecaciones (phpstan/phpstan-deprecation-rules) encuentra llamadas a APIs marcadas como @deprecated en tus dependencias, algo que PHPCompatibility no ve. Con nivel 5-6 también cazará muchas de las comparaciones y conversiones de tipos que romperán en tiempo de ejecución.
  • Rector en modo --dry-run con el conjunto de reglas de la versión objetivo te muestra un diff de todo lo que puede corregir automáticamente.

El resultado de esta fase es una lista cuantificada: N incidencias corregibles automáticamente, M que requieren decisión humana, K dependencias a sustituir. Con esa lista se puede estimar de verdad.

7.3 Corrección automatizada con Rector

Rector es la herramienta que convierte una migración de semanas en días. Un fichero de configuración mínimo para subir a 8.4 sería:

<?php
// rector.php
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;

return RectorConfig::configure()
    ->withPaths([__DIR__ . '/src', __DIR__ . '/app', __DIR__ . '/modules'])
    ->withSets([LevelSetList::UP_TO_PHP_84])
    ->withSkip([__DIR__ . '/vendor', __DIR__ . '/var']);

// Ejecutar:  vendor/bin/rector process --dry-run   (revisar)
//            vendor/bin/rector process             (aplicar)

Rector corrige los nulables implícitos, sustituye funciones deprecadas, añade #[\ReturnTypeWillChange] donde toca, moderniza la sintaxis de arrays y closures, y declara propiedades dinámicas como propiedades reales cuando puede inferirlas. Aplica los cambios por lotes (un conjunto de reglas por commit) para que la revisión de código sea abordable, y no actives las reglas de «calidad de código» en el mismo pase que las de migración: mezclar refactor con compatibilidad es la forma más rápida de no saber qué rompió qué.

7.4 Pruebas: automatizadas, de humo y con datos reales

Si tienes tests, ejecútalos en un entorno con la versión de destino desde el primer día (un contenedor con la imagen oficial php:8.4-fpm o php:8.5-fpm es suficiente). Si no los tienes —la situación más frecuente en aplicaciones heredadas—, no intentes escribir una suite completa ahora; escribe tests de humo de los flujos que dan dinero: login, alta de pedido, checkout con cada pasarela, generación de factura, sincronización con el ERP, exportación contable. Diez pruebas de extremo a extremo (Playwright o Cypress contra el staging) cubren más riesgo real que quinientos tests unitarios de utilidades.

Las pruebas deben ejecutarse con una copia anonimizada de la base de datos de producción. Las rupturas de PHP 8 dependen de los datos: un null donde se esperaba una cadena solo aparece con el cliente que se registró en 2014 sin teléfono. Y configura el entorno de pruebas para que las deprecaciones se conviertan en excepciones, de forma que no se te escape ninguna:

; php.ini (staging / CI)
error_reporting = E_ALL
display_errors = Off
log_errors = On
error_log = /var/log/php/deprecations.log

// bootstrap de tests: cualquier deprecación es un fallo
set_error_handler(function (int $no, string $str, string $file, int $line) {
    if ($no === E_DEPRECATED || $no === E_USER_DEPRECATED) {
        throw new ErrorException($str, 0, $no, $file, $line);
    }
    return false;
});

7.5 Despliegue progresivo y plan de vuelta atrás

Nunca cambies la versión de PHP «in situ» en el servidor de producción un viernes. Las opciones seguras, de menos a más sofisticada:

  • Dos pools de PHP-FPM en paralelo (8.2 y 8.5) en el mismo servidor, y cambiar el fastcgi_pass de Nginx de uno a otro. Volver atrás es cambiar una línea y recargar Nginx: segundos.
  • Servidor o contenedor nuevo con la versión de destino y conmutación en el balanceador o el DNS, manteniendo el antiguo encendido 48-72 horas.
  • Canary: enviar un 5-10% del tráfico (o solo el tráfico interno) a la versión nueva durante unos días, vigilando tasas de error y latencia antes de mover el resto.

Sea cual sea la estrategia, define antes qué métricas te hacen volver atrás (por ejemplo, tasa de errores 5xx superior al 0,5%, caída de conversión del checkout, cola de trabajos cron atascada) y quién decide. Y protege el opcache: tras el cambio, el primer minuto de tráfico compila todo de nuevo; precalienta con un warmup de las URLs principales si el sitio es grande.

7.6 Limpieza de deprecaciones y cierre

Una vez estable en producción, deja el registro de deprecaciones activo entre dos y cuatro semanas y revisa el log semanalmente. Verás avisos que ninguna prueba detectó: el informe mensual, el cron trimestral, la integración con el proveedor que solo envía pedidos los lunes. Cada aviso corregido ahora es un fatal error evitado en PHP 9. Cierra el proyecto actualizando composer.json ("php": "^8.4"), la imagen Docker, la documentación del entorno y la CI, para que nadie pueda volver atrás por accidente.

8. Los errores que vemos después de migrar (y cómo evitarlos)

Aunque el proceso se haga bien, hay una serie de problemas que aparecen una y otra vez en las semanas posteriores a una migración de PHP. Conviene tenerlos en el radar desde el principio.

  • Serialización y cachés: objetos guardados en sesión, Redis o en la base de datos con la versión antigua que fallan al deserializar en la nueva (cambios en unserialize() en 8.3, clases con __wakeup). Solución: vaciar cachés de objetos y sesiones en el despliegue y aceptar que los usuarios tendrán que volver a iniciar sesión.
  • Precisión y redondeo de importes: el ajuste de round() en 8.4 y los cambios en la conversión float-cadena pueden mover un céntimo en facturas y totales de carrito. Compara un lote de facturas históricas regenerado en la versión nueva con las originales antes de dar por buena la migración.
  • Locales y formato de fechas: strftime() está deprecada desde 8.1; el código que formatea fechas en español con ella debe pasar a IntlDateFormatter. Es habitual en plantillas de correo y PDFs.
  • Cron y scripts fuera de la web: el binario de CLI puede seguir apuntando a la versión antigua aunque PHP-FPM ya esté en la nueva (o al revés). Verifica php -v en los crontabs y en los servicios de cola.
  • Configuración perdida: el php.ini nuevo no hereda tus ajustes de memory_limit, upload_max_filesize, max_execution_time u opcache. php --ini=diff (8.5) o un diff manual entre ambos ficheros lo resuelve.
  • Rendimiento inesperadamente peor: casi siempre por opcache desactivado o con opcache.max_accelerated_files demasiado bajo en la instalación nueva. Cuando se configura bien, el resultado es el contrario: cada versión mayor de PHP 8 ha recortado tiempos de respuesta y consumo de CPU, algo que se nota directamente en las Core Web Vitals y en la factura del hosting.
  • Seguridad regresiva: aprovechar la migración para activar session.cookie_secure, session.cookie_samesite y desactivar expose_php cuesta cinco minutos. Si además tienes una tienda online, es buen momento para una auditoría de seguridad del ecommerce, porque el código que se ha tocado en la migración es exactamente el que más conviene revisar.

¿Tu plataforma sigue en una versión de PHP sin soporte?

En Keliam auditamos tu código y tus dependencias, estimamos el esfuerzo real de subir a PHP 8.4/8.5, ejecutamos la migración con Rector, pruebas y despliegue progresivo, y nos quedamos manteniendo la plataforma para que la próxima versión —incluida PHP 9— no vuelva a ser un proyecto de urgencia.

Habla con nuestro equipo →

9. Cuánto cuesta y cuánto tarda: referencias realistas

La pregunta que todo responsable hace antes de aprobar el proyecto. Sin conocer el código no se puede dar una cifra, pero sí órdenes de magnitud a partir de lo que vemos en proyectos reales:

  • Aplicación moderna (Laravel/Symfony reciente, tests, dependencias al día), de 8.2/8.3 a 8.4/8.5: de dos a cinco días. La mayor parte es actualizar dependencias y revisar el diff de Rector.
  • WordPress/WooCommerce con 30-50 plugins, de 8.0/8.1 a 8.4: de una a dos semanas, casi todo en identificar y sustituir plugins abandonados y en probar el checkout con cada pasarela y método de envío.
  • Aplicación a medida heredada (7.4 o anterior, sin tests, 100-300k líneas): de tres a ocho semanas. El coste lo marcan las propiedades dinámicas, las comparaciones laxas y las librerías sin mantenimiento, no el volumen de código en sí. Aquí el análisis estático previo (fase 7.2) es lo que permite dar una estimación cerrada.
  • PrestaShop 1.7 o Drupal 7: no es una migración de PHP, es una migración de plataforma, y hay que presupuestarla como tal.

El retorno se mide en tres partidas: riesgo de seguridad eliminado (una brecha por una CVE sin parche cuesta mucho más que cualquier migración), ahorro de infraestructura (menos CPU por petición) y velocidad de desarrollo (poder usar librerías actuales y contratar desarrolladores que no quieren tocar PHP 7). Y hay un cuarto factor cada vez más relevante: los ciberseguros y los cuestionarios de seguridad de clientes grandes preguntan explícitamente por software sin soporte.

Conclusión

PHP 8.4 y 8.5 no son versiones de transición: property hooks, visibilidad asimétrica, el operador pipe, clone with, la nueva API DOM y la extensión URI cambian cómo se escribe PHP profesional, y a la vez cierran el ciclo de deprecaciones que PHP 9 convertirá en errores. Migrar hoy tiene un coste acotado y conocido; posponerlo tiene un coste creciente y desconocido, que se paga en CVE sin parche, plugins que no se pueden actualizar y un salto a PHP 9 mucho más duro. El método no tiene misterio: inventario, análisis estático, Rector, pruebas con datos reales, despliegue con vuelta atrás y limpieza de deprecaciones. Lo que marca la diferencia es hacerlo con calma ahora, mientras 8.2 todavía recibe parches, y no cuando el hosting anuncie que apaga la versión antigua dentro de quince días.

Preguntas frecuentes sobre migrar PHP 8

¿Debo migrar a PHP 8.4 o directamente a 8.5?

Si tu stack lo permite (frameworks y CMS declaran compatibilidad), ve a 8.5: tendrás un año más de soporte y las deprecaciones adicionales que introduce te dejan más cerca de PHP 9. Si algún componente crítico solo está probado en 8.4, quédate en 8.4 y planifica 8.5 para 2027; el salto entre ambas es pequeño.

¿Cuándo sale PHP 9?

No hay fecha oficial. El proyecto ha indicado que no habrá PHP 9 hasta acumular suficientes cambios incompatibles, y mientras tanto la rama 8.x sigue con una versión menor cada noviembre. Lo que sí es seguro es que todo lo deprecado en 8.x se eliminará en 9.0, así que mantener el log limpio de avisos es la mejor preparación.

¿Puedo seguir en PHP 8.1 si mi hosting lo mantiene?

Técnicamente sí; responsablemente no. Los backports de distribuciones como Ubuntu o RHEL cubren solo una parte de las vulnerabilidades y dependen de que alguien los haga. Además, tus frameworks y plugins irán subiendo el mínimo y dejarás de poder actualizarlos, con lo que el problema de seguridad se traslada a la capa de aplicación.

¿Rector es seguro de aplicar en código de producción?

Sí, siempre que lo apliques por conjuntos de reglas, revises el diff y ejecutes pruebas después. Rector solo cambia lo que las reglas describen y es determinista; el riesgo está en aplicarlo «a ciegas» junto con reglas de refactor que alteran comportamiento. Para migraciones de versión, limita las reglas a los level sets de PHP.

¿Cuánto mejora el rendimiento al pasar de PHP 7.4 a 8.4/8.5?

Depende de la aplicación, pero en cargas típicas de CMS y ecommerce las mejoras acumuladas del motor, el JIT y las optimizaciones de arrays y cadenas entre 7.4 y 8.4 son claramente perceptibles en tiempo de respuesta y consumo de CPU, siempre que opcache esté bien configurado. Mide antes y después con tu propia carga; es el argumento más convincente para dirección.

Scroll al inicio