La línea del log decía `Redirect allowed: host=trusted.example`, y la redirección acabó en un sitio que no era trusted.example ni de lejos. Pasé una noche larga peleándome con parse_url() y con una URL que el navegador interpretaba de una manera y nuestra allowlist de otra. Así que cuando me preguntan cuál es la gran novedad de PHP 8.5, no digo el operador pipe, aunque sea lo que sale en todas las diapositivas de las conferencias. Mi respuesta es la extensión URI, y aquí voy a defenderla.
<?php
use Uri\Rfc3986\Uri;
$uri = new Uri('https://php.net/releases/8.5/en.php');
echo $uri->getHost(); // "php.net"Primero, situémonos. PHP 8.5 salió el 20 de noviembre de 2025. Laravel 12 y 13 funcionan con PHP 8.3 a 8.5, los hostings ya lo ofrecen y la próxima versión llega este noviembre. Así que es buen momento para dejar de preguntar qué hay de nuevo y empezar a preguntar qué ha cambiado de verdad en nuestro código. El operador pipe se lleva casi toda la atención. Lo que va a importar en tus informes de incidentes es `Uri\Rfc3986\Uri` y su hermano WHATWG.
Ahora, el mejor argumento del otro lado, que es sólido. Los pipes cambian cómo se lee el código en cada pantalla que abres. Las llamadas anidadas que se leen de dentro hacia fuera son un pequeño impuesto que pagas todo el día, y `|>` lo elimina para cualquier función normal, sin necesidad de una colección ni de envolver nada con `Str::of()`. Una característica que ves en cien archivos puede importar fácilmente más que una que usas en tres. Lo acepto. Y añado que `array_first()` y `array_last()` van a quitar más búsquedas feas con `array_key_last()` de las que nos gustaría admitir.
Mi problema es que las mejoras de legibilidad se reparten muy finas, y el pipe tiene asperezas que las mantienen modestas. Cada paso tiene que ser un callable de un solo argumento, así que en cuanto necesitas `str_replace` ya estás escribiendo una arrow function, y encima tienes que meterla entre paréntesis. Los pipelines reales acaban siendo una mezcla de `trim(...)` y `(fn($s) => ...)`. Queda mejor que anidar, pero no muchísimo mejor. Un equipo que no lo adopte no pierde nada que no le pueda devolver una variable local con un buen nombre.
Parsear URLs es otra historia. parse_url() siempre fue permisivo: te devolvía un array para entradas que un navegador, un proxy y tu cliente HTTP leerían cada uno a su manera. En ese hueco nacen las redirecciones abiertas y los bypass de allowlists contra SSRF. Ahora obtienes un objeto construido según un estándar publicado, RFC 3986 o WHATWG, y eliges el que coincide con el sistema que hay al otro lado. Esa elección es la verdadera mejora. Tienes que decidir si validas como un servidor o como un navegador, una pregunta que parse_url() nunca te hizo.
La llamada en sí es casi demasiado simple para enseñarla, y en el fondo esa es la gracia. No necesitas un refactor, ni un debate sobre la guía de estilo, ni una votación del equipo. Buscas los sitios donde un host o un esquema decide quién entra y cambias el parseo.
Para ser justo con el resto de 8.5: `#[\NoDiscard]` va en la misma línea, porque te avisa de un `save()` cuyo false nadie comprobó, y los errores fatales con backtrace van a acortar más de una caza de agotamiento de memoria. Ahí es adonde iría después. Los pipes vienen detrás, en helpers nuevos y mappers de datos, siempre que dejen una línea más clara. Muchos escribimos llamadas anidadas en Go tan felices, y a nadie se le ha acabado la carrera por eso.
Así que te lanzo una pregunta, porque tú conoces tu código y yo no. Si ya te has pasado a 8.5, ¿qué cambiaste primero, y encontró algún bug real o fue todo cuestión de que el código se viera mejor? Si has sustituido parse_url() por la extensión URI, ¿resultó RFC 3986 o WHATWG el valor por defecto adecuado para tus redirecciones y webhooks, y cómo lo decidiste?




Comentarios
Aún no hay comentarios — escribe el primero.
Inicia la conversación
Sin cuenta ni contraseña — introduce tu correo y te enviamos un enlace de acceso de un solo uso. ¿Primera vez? Todo se configura automáticamente.
Tu valoración se aplicará automáticamente al iniciar sesión.
Revisa tu bandeja de entrada
Hemos enviado un enlace de acceso a …. Ábrelo en este dispositivo — esta pestaña te conectará automáticamente.
¿No llega nada? Mira en la carpeta de spam — y marca el correo como «No es spam» para que la próxima vez llegue directo.