The Daily Commit · Edición de sección Portada PHP AI Dev EN DE FR ES

The Php Times

El Editorial — Ecosistema

Que las deprecaciones rompan tu build, y que PHP 8.6 sea la excusa


PHP 8.6 llega el 19 de noviembre de 2026 como una versión ligera: aplicación parcial de funciones, una clase Duration y unas treinta deprecaciones.

9 de septiembre de 2026 Un editorial de Kai

Mi tesis: el salto de versión es trivial, así que dedica el tiempo ahorrado a que los avisos de deprecación rompan tu pipeline en lugar de pasar de largo. Aquí va el argumento, la objeción honesta y los dos puntos que ningún contador va a detectar.

Abre el fichero que ejecuta de verdad tu suite de tests en CI. No el README, el comando real. En algún punto, escrita hace años por alguien que ya trabaja en otra empresa, hay una decisión: los avisos de deprecación son ruido. Puede ser un flag de error_reporting, puede ser un listener que se los traga, puede ser simplemente un log que nadie lee. El build sale verde. Y sigue saliendo verde durante años, hasta la versión mayor en la que cada uno de esos avisos silenciosos se convierte en un error fatal y resulta que ese verde era un mentiroso muy educado.

terminal
php -d error_reporting=E_ALL -d display_errors=1 vendor/bin/phpunit

Así que esta es mi postura sobre PHP 8.6, que sale el 19 de noviembre de 2026: lo interesante no es la release, es el permiso que te da. Aquí no hay reescritura del motor, ni errores de tipos en masa, ni el muro que fue el salto a 8.0. Una aplicación bien testeada en 8.4 o 8.5 se actualiza en una tarde. Coge los días que ibas a reservar para esta migración y gástalos en que tu pipeline salga con código distinto de cero cuando tu propio código lanza una deprecación. No un informe. No un dashboard. Un build rojo.

Que quede claro: no es una versión sin alegrías. La aplicación parcial de funciones pasó 33 a 0, un margen que prácticamente nunca ves en cuestiones de sintaxis, y hace que el operador pipe de 8.5 valga por fin la pena, porque puedes meter una llamada a función con un hueco dentro de una tubería en lugar de envolverlo todo en una arrow function. Time\Duration salió 35 a 1 y le da a un timeout un tipo sin ambigüedades, algo que agradecerá cualquiera que haya pasado milisegundos a algo que esperaba segundos. Hay clamp(), un enum SortDirection, propiedades readonly con valores por defecto, #[\Override] en constantes de clase y un json_decode() que te dice dónde se rompió realmente el parseo. Una trampa de los parciales que conviene interiorizar: los argumentos que le pasas se evalúan cuando construyes la closure, no cuando la llamas, así que un parcial que fija algo leído de un contenedor con ámbito de petición captura ese valor una vez y se queda con él. También hay fontanería nueva de bajo nivel para polling de I/O en el core, que le importa muchísimo a quien mantiene event loops y absolutamente nada a esta columna.

El grueso de 8.6 son unas treinta deprecaciones, y la mayoría son trabajo que te hace una máquina. is_double(), is_integer(), doubleval() y spl_object_hash() tienen reemplazos obvios. Pasar un objeto donde se espera un array está en vías de extinción en array_walk(), mb_convert_variables(), http_build_query() y los parámetros de los filtros zlib y bzip2, y la votación de array_walk() fue 41 a 3, así que nadie está peleando por ese comportamiento. readonly deja de poder usarse como nombre de función, 39 a 1. is y let pasan a ser vocabulario reservado, que es el motor guardándose sitio para pattern matching más adelante. Devolver un valor desde un bloque finally queda deprecado con la votación más contundente de toda la RFC, 39 a 3. El set PHP_86 de Rector más una lectura cuidadosa del diff se ocupan de casi todo. Precisamente por eso el build que falla es asequible ahora: la lista es larga pero cada arreglo es barato, así que puedes llegar a cero y luego defender el cero.

La objeción honesta, y yo mismo la he hecho: tú no controlas el código de vendor. Convierte las deprecaciones en fallos de build y la siguiente versión menor de un framework o de una librería cliente te puede pintar el pipeline de rojo por algo que no puedes parchear, y entonces la presión es congelar dependencias, que es la forma de quedarte tirado. Es justo. La respuesta es que son dos poblaciones distintas y merecen dos políticas distintas. Tu propio namespace: tolerancia cero, falla de inmediato. Todo lo que cuelga de vendor: una línea base contada, en la que se te permite estar por encima de cero, con el número visible y bajando, y un issue abierto aguas arriba cuando no se mueve. El PHPUnit bridge de Symfony lleva años haciendo umbrales por paquete, y puedes aproximar lo mismo con un manejador de errores de veinte líneas. Lo que no puedes hacer es tratar ambas poblaciones como ruido porque una de ellas es incómoda.

Hay un punto de la lista que no es un buscar y reemplazar, y merece tiempo en el calendario en vez de un viernes por la tarde. Oniguruma, el motor de expresiones regulares detrás de la familia mb_ereg de mbstring, dejó de recibir mantenimiento aguas arriba el 24 de abril de 2025. La respuesta de PHP es deprecación en 8.6 y eliminación en 9.0. Mover mb_ereg(), mb_ereg_replace() y mb_regex_encoding() a preg_* con el modificador u cambia la semántica, no solo la ortografía: los dos motores discrepan en suficientes detalles como para que un patrón siga haciendo match y empiece a hacer match de un poco más o de un poco menos que antes. Ese modo de fallo no lanza nada. Simplemente deja pasar en silencio una cadena por tu validador. Escribe un test por patrón antes de tocarlo, y si no puedes enumerar tus patrones, esa enumeración es el primer ticket. Drupal ya tiene un issue abierto por esto, lo cual te dice que el uso no es exótico.

Y luego está la categoría que ningún contador de deprecaciones va a sacar a la luz, porque no hay nada deprecado. Los valores por defecto de sesión en el INI se endurecen en 8.6: session.use_strict_mode pasa a 1, session.cookie_httponly pasa a 1 y session.cookie_samesite pasa a "Lax". Son tres buenos cambios, y cada uno puede romper un flujo de POST entre sitios o un trozo de JavaScript que lleva leyendo la cookie de sesión desde 2017. Mete esos tres valores en tu propio fichero ini con la configuración que hayas decidido, para que un cambio aparezca en un pull request y no en un canal de soporte. En la misma línea: trim() y compañía ahora eliminan el form feed por defecto, lo cual importa si cortas texto de ancho fijo; preg_grep() devuelve false en caso de error en lugar de un array parcial; un montón de funciones que antes avisaban ahora lanzan excepciones. Es muy posible que tu suite de tests pase por encima de todo esto sin enterarse. UPGRADING sigue siendo un fichero que se lee con café, no un fichero al que se le hace grep.

Sobre lo que quiero discutir de verdad es la política, no la release. La toolchain de Go se niega a compilar un import sin usar, y los desarrolladores de Go dejaron de quejarse de eso unos diez minutos después de acostumbrarse. PHP te ofrece la misma palanca, solo que la deja apagada por defecto y espera que tú seas el adulto. Así que: ¿falla hoy tu build ante una deprecación lanzada dentro de tu propio directorio src? Si no, ¿qué te lo impidió, un árbol de vendor que no puedes arreglar o una línea base que nadie quería mantener? Y a los equipos que corren 400 paquetes en composer.json, me interesa de verdad saber cómo mantenéis honesto el contador de vendor sin congelar las dependencias. Respuestas en los comentarios, sobre todo las que no funcionaron.

Existe una versión de esta migración en la que subes la restricción de versión, ves la suite en verde y despliegas. Va a funcionar. También va a significar que cada aviso que no leíste este noviembre vuelve como error fatal el día que intentes pasar a 9.0, en bloque, con prisa y probablemente durante un congelado de releases. El momento barato es la versión aburrida. Esta es la versión aburrida.

Valora este artículo: 0

Tribuna de lectores

Aún no hay aportaciones — abre el debate.

← Ecosistema — Page B1

"All the Code That's Fit to Ship" · The Daily Commit · Edición de pantalla · Información legal · Política de privacidad