PHP 8.5 se publicó el 20 de noviembre de 2025 y ya está disponible en la mayoría de servidores y paneles. No es una versión revolucionaria, pero trae varias mejoras que hacen el código más legible, con una novedad que se esperaba desde hace años: el pipe operator.

Además, PHP 8.5 es compatible con Laravel 12 y Laravel 13, así que si mantienes una aplicación actualizada puedes empezar a usarlo.

El pipe operator |>

El pipe operator permite encadenar llamadas a funciones de izquierda a derecha: el resultado de cada paso se pasa como argumento al siguiente. Así evitas tanto las funciones anidadas como las variables intermedias.

Por ejemplo, para convertir un título en un slug sencillo, antes tenías que escribir algo así:

$slug = strtolower(
    str_replace(['.', '/', '…'], '', str_replace(' ', '-', trim($title)))
);

Con el pipe operator se lee en el orden en que ocurre:

$slug = $title
    |> trim(...)
    |> (fn (string $s) => str_replace(' ', '-', $s))
    |> (fn (string $s) => str_replace(['.', '/', '…'], '', $s))
    |> strtolower(...);

Dos detalles a tener en cuenta:

  • A la derecha del |> va un callable que recibe un único valor. Las funciones que solo necesitan ese valor se pueden pasar directamente con la sintaxis de primera clase, como trim(...) o strtolower(...).
  • Si la función necesita más argumentos, como str_replace(), envuélvela en una función flecha entre paréntesis.

Clonar objetos modificando propiedades: clone with

clone() acepta ahora un segundo argumento con las propiedades que quieres cambiar en la copia. Es muy útil para los métodos with...() de los objetos inmutables:

final class Post
{
    public function __construct(
        public readonly string $title,
        public readonly string $status,
    ) {}

    public function withTitle(string $title): static
    {
        return clone($this, [
            'title' => $title,
        ]);
    }
}

Hay una limitación: desde fuera de la clase no puedes modificar así una propiedad readonly, salvo que su visibilidad de escritura sea public(set).

Extensión URI: adiós a los problemas de parse_url()

PHP 8.5 incluye una extensión nativa para analizar y modificar URLs siguiendo los estándares: RFC 3986 y también el estándar WHATWG, que es el que usan los navegadores. Es la alternativa a parse_url() cuando necesitas un análisis fiable:

use Uri\Rfc3986\Uri;

$uri = new Uri('https://robertostory.com/blog?page=2');

$uri->getScheme(); // "https"
$uri->getHost();   // "robertostory.com"
$uri->getPort();   // null

array_first() y array_last()

Por fin hay funciones directas para obtener el primer y el último elemento de un array. Devuelven null si el array está vacío, así que combinan bien con el operador ??:

// Antes
$first = $array[array_key_first($array)] ?? null;

// Con PHP 8.5
$first = array_first($array);
$last = array_last($array);

$plan = array_first($plans) ?? 'gratuito';

#[\NoDiscard]: avisos si ignoras un valor importante

El atributo #[\NoDiscard] marca funciones cuyo valor de retorno no debería ignorarse. Si llamas a la función sin usar el resultado, PHP muestra un aviso:

#[\NoDiscard('Comprueba si el pago se ha procesado')]
function processPayment(Order $order): bool
{
    // ...
}

processPayment($order);      // Aviso: el valor de retorno debería usarse

(void) processPayment($order); // Ignorado de forma explícita: sin aviso

Es muy útil en métodos que devuelven un resultado que hay que comprobar, como un pago, una validación o una copia inmutable de un objeto.

Otras mejoras

  • Backtraces en los errores fatales: errores como Maximum execution time exceeded incluyen ahora la traza de llamadas, lo que facilita mucho saber dónde se quedó atascado el código.
  • Closures en expresiones constantes: puedes usar closures, siempre static y sin use, en lugares como los argumentos de los atributos.
  • Persistencia de los share handles de cURL entre peticiones, útil en aplicaciones de larga duración.

Deprecaciones que conviene revisar

Antes de actualizar, revisa si tu código usa alguna de estas construcciones:

  • Las comillas invertidas (`comando`) como alias de shell_exec(). Usa shell_exec() directamente.
  • Los nombres de cast no canónicos, como (boolean), (integer) o (double). Usa (bool), (int) y (float).
  • La redeclaración de constantes.
  • La directiva disabled_classes de php.ini, que se ha eliminado.

¿Debo actualizar ya?

Si tu aplicación usa Laravel 12 o 13 y tus dependencias son compatibles, PHP 8.5 es una actualización con poco riesgo. Prueba primero en local o en staging, revisa las deprecaciones y comprueba que los paquetes de Composer la admiten.

Y si tu aplicación todavía está en una versión antigua de PHP o Laravel, en este artículo cuento cómo actualicé una aplicación de Laravel 5.5 a Laravel 13. Si necesitas ayuda con la tuya, escríbeme.

Fuentes