🚀
Hosting

PHP 8.5: The Pipe Operator, the URI Extension and Other New Features

12.11.2026
← All articles

PHP 8.5 was released in November 2025. It is less sweeping than 8.4, but it adds several features that make everyday code noticeably cleaner. The headline is the pipe operator for chaining function calls. There is also a standard URI extension, functions for the first and last array element, and an attribute that warns when a return value is ignored.

The pipe operator

Passing a value through several functions in PHP usually means nested calls that read right to left. Turning a title into a URL slug needs trimming, lowercasing and replacing spaces. The new |> operator passes the value left to right, in the order the steps happen. Here is slug generation for a Bukhara hotel website:

$title = '  Lyuks Xona Bog Tomonda  ';

// Before: nested calls
$slug = str_replace(' ', '-', strtolower(trim($title)));

// PHP 8.5: pipe operator
$slug = $title
    |> trim(...)
    |> strtolower(...)
    |> (fn($s) => str_replace(' ', '-', $s));

echo $slug; // lyuks-xona-bog-tomonda

Two rules apply. The right-hand side must be a callable taking one parameter, which is why first-class callable syntax like trim(...) is used. Arrow functions must be wrapped in parentheses, otherwise you get a parse error.

Clone with new property values

Readonly properties have existed since 8.1, but making a copy with one changed value was awkward because a clone cannot rewrite a readonly property. In 8.5, clone() accepts an array of new values as its second argument, so return clone($this, ['amount' => $newAmount]); works cleanly inside an immutable value object such as a price with a discount method.

The URI extension

parse_url() follows no standard exactly and can interpret odd URLs differently from browsers, which has caused security bugs. PHP 8.5 bundles a URI extension with Uri\Rfc3986\Uri for RFC 3986 and Uri\WhatWg\Url for the WHATWG standard browsers use.

$uri = new Uri\Rfc3986\Uri('https://example.uz/katalog?page=2');

echo $uri->getHost();  // example.uz
echo $uri->getPath();  // /katalog
echo $uri->getQuery(); // page=2

This matters for any site that validates user-supplied links, for example when redirects must stay on your own domain to avoid open-redirect bugs.

array_first(), array_last() and #[\NoDiscard]

array_first() and array_last() return the first or last value directly, or null for an empty array, replacing reset() and end() tricks. A function marked #[\NoDiscard] triggers a warning if its result is unused, which suits functions like a save routine that reports failure through its return value. Prefix the call with (void) to ignore the result intentionally.

Better debugging

Fatal errors such as memory exhaustion or timeouts now include a backtrace, so it is easier to see how the code got there. New get_error_handler() and get_exception_handler() return the currently installed handlers. Static closures are allowed in constant expressions such as attribute arguments, and persistent cURL share handles let repeated requests reuse DNS and connection data.

Deprecations and upgrading

These do not stop a site, but they add Deprecated notices. Before moving to 8.5, confirm that your CMS and plugins officially support it, since plugins often need time after a new release. On sayt.uz hosting the PHP version is chosen per site in ISPmanager, so you can try 8.5 on a test subdomain such as test.example.uz first. If the version is not listed in the panel, ask support through the cabinet.

Related articles

📦 Moving Away from Plesk: What to Take and What Not to Forget ⏱️ How an every-minute cron job weighs on your server — and how to lighten it 🧪 Deploying a Flask App to Hosting: wsgi, Passenger, Gunicorn and Safe Settings 🧰 Enabling PHP extensions: intl, gd, imagick and zip
🌐 Language
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский 🇬🇧 English ✓