Heads-up: PHP 8.5 is still in development; the first General Availability build is slated for 20 November 2025. Nightly tarballs and Docker images (
php:8.5.0-dev) are already rolling if you want to experiment.
TL;DR — highlight reel
| Area | Feature |
|---|---|
| Language syntax | Pipeline operator ` |
| Standard library | {% raw %}array_first(), array_last(), new IntlListFormatter, curl_multi_get_handles(), locale_is_right_to_left() |
| Attributes | #[\NoDiscard] + (void) cast |
| Core tweaks | Directory becomes an opaque/final class |
| Perf / IO | Native Zstandard & Brotli compression |
The rest of the post dives into each of these with examples and links to the RFCs.
1- New language constructs
1.1 Pipeline operator |>
Approved in February 2025, the pipe feeds the LHS value into the callable on the RHS and evaluates left-to-right.
$result = "Hello World" |> htmlentities(...) |> str_split(...) |> fn($x) => array_map(strtoupper(...), $x) |> fn($x) => array_filter($x, fn ($v) => $v !== 'O'); var_dump($result); // ['H','E','L','L','W','R','D'] 1.2 Records — immutable value objects
The record keyword (RFC under discussion but trending positive) lets you declare by-value, immutable types with almost zero boilerplate.
record Point(int $x, int $y); $origin = &Point(0, 0); // the leading “&” signals record instantiation echo $origin->x; // 0 1.3 final in constructor property-promotion
Soon you can mark promoted properties as final, guaranteeing they’ll never change after construction. Voting is already overwhelmingly “yes”.
class User { public function __construct( final string $id, public string $name, ) {} } 1.4 Closures in constant expressions
Static closures are now legal inside const, attribute arguments, and default property/parameter values — handy for default callbacks. Implemented for 8.5.
const DEFAULT_FILTER = static function (mixed $v): bool { return !empty($v); }; 1.5 #[\NoDiscard] + (void) cast
Mark functions whose return value must be consumed; if you really want to ignore it, cast the call to (void) to silence the warning.
#[\NoDiscard('You probably meant to use this')] function compute(): array { return [...]; } (void) compute(); // explicitly discard – no warning 2- Standard-library additions
| ✨ New API | Why you’ll care |
|---|---|
array_first() / array_last() | Grab the first or last element in O(1) without touching the internal pointer. |
curl_multi_get_handles() | Enumerate all handles inside a multi-curl resource. |
IntlListFormatter | Human-friendly lists with i18n (e.g. “apples, pears and peaches”). |
locale_is_right_to_left() | Quick RTL check without ICU look-ups. |
php --ini=diff | CLI flag that prints only the INI entries you’ve tweaked. |
PHP_BUILD_DATE | Exact build timestamp baked into the binary. |
$items = ['🍎','🍐','🍑']; echo array_first($items); // 🍎 echo array_last($items); // 🍑 3- Engine & core library tweaks
3.1 Directory is now opaque
You can no longer new Directory() or clone/serialize one; treat it like the resource object it really is.
$dir = dir('.'); clone $dir; // Fatal error new Directory(); // Fatal error 3.2 Modern compression built-in
Zstandard and Brotli join zlib, giving you fast, web-native compression out of the box.
$zip = zstd_compress($data); $plain = brotli_uncompress($zip); 4- Deprecations
- All
MHASH_*constants are on the chopping block. - Expect a fresh round of minor edge-case clean-ups as 8.5 stabilises.
5- Wrap-up
PHP 8.5 isn’t a revolutionary release, but it packs a ton of ergonomic polish:
- Functional-style pipes for cleaner data flows
- Boilerplate-free value objects
- Safer APIs that nudge you away from foot-guns
- And plenty of small but mighty quality-of-life bumps
Give the nightlies a spin, file bugs, and 🎉 happy hacking!
Further reading
- 📜 Pipeline operator RFC — https://wiki.php.net/rfc/pipe-operator-v3
- 📜 Records RFC — https://wiki.php.net/rfc/records
- 📜 Full 8.5 change-log at PHP.Watch — https://php.watch/versions/8.5
Top comments (0)