Skip to content

PHP Tutorial Modern PHP Features

What Is New in PHP 8.5

Lesson 236 of 369 2 min read By Deepak Paswan Updated Oct 5, 2026

PHP 8.5 was released on 20 November 2025. As with the previous lessons, this code needs PHP 8.5 or newer and cannot run on older versions (including the PHP 8.2 server used to test this course). The examples follow the official release notes at php.net/releases/8.5.

The pipe operator |>

The pipe operator takes the value on the left and passes it to the callable on the right. It lets you read a chain of steps from left to right, without nesting calls or using temporary variables.

index.php
PHP
<?php
$title = "  PHP 8.5 Is Here.  ";

$slug = $title
    |> trim(...)
    |> (fn(string $s) => str_replace(" ", "-", $s))
    |> (fn(string $s) => str_replace(".", "", $s))
    |> strtolower(...);

echo $slug;   // php-85-is-here

Each step receives the result of the step before it. First-class callables (trim(...)) and arrow functions both work. Arrow functions are wrapped in brackets.

The same without the pipe operator:

index.php
PHP
<?php
$title = "  PHP 8.5 Is Here.  ";

$slug = strtolower(str_replace(".", "", str_replace(" ", "-", trim($title))));

echo $slug;
Output
OUTPUT
php-85-is-here

The nested version reads inside out. The piped version reads in the order things happen.

array_first() and array_last()

Two functions return the first or last value of an array, or null if the array is empty.

index.php
PHP
<?php
$events = ["start", "middle", "end"];

echo array_first($events);   // start
echo array_last($events);    // end

Older code used $arr[array_key_first($arr)] or end($arr).

index.php
PHP
<?php
function firstValue(array $items): mixed
{
    return $items === [] ? null : $items[array_key_first($items)];
}

function lastValue(array $items): mixed
{
    return $items === [] ? null : $items[array_key_last($items)];
}

echo firstValue(["start", "middle", "end"]) . " " . lastValue(["start", "middle", "end"]);
Output
OUTPUT
start end

clone with

PHP 8.5 lets clone accept new property values, which makes “with” methods on readonly classes much shorter.

index.php
PHP
<?php
readonly class Color
{
    public function __construct(
        public int $red,
        public int $green,
        public int $blue,
        public int $alpha = 255,
    ) {}

    public function withAlpha(int $alpha): self
    {
        return clone($this, ["alpha" => $alpha]);
    }
}

$blue = new Color(79, 91, 147);
$transparent = $blue->withAlpha(128);

The #[\NoDiscard] attribute

Warns when a function’s return value is ignored. It helps with functions where the result must be checked.

index.php
PHP
<?php
#[\NoDiscard]
function getPhpVersion(): string
{
    return "PHP 8.5";
}

getPhpVersion();   // Warning: the return value should be used

Closures in constant expressions

Static closures and first-class callables can be used where constant expressions are allowed, for example in attribute arguments and constants.

The URI extension

A new always-available extension parses and normalises URIs following RFC 3986 and the WHATWG URL standard.

index.php
PHP
<?php
use Uri\Rfc3986\Uri;

$uri = new Uri("https://php.net/releases/8.5/en.php");

var_dump($uri->getHost());   // string(7) "php.net"

Other changes

  • A persistent cURL share handle (curl_share_init_persistent()).
  • Various deprecations and smaller improvements. Read the official migration guide before upgrading a large project.

What to do with this

  • Learn the idea of each feature, so you recognise it in code.
  • Use features from versions your production server runs.
  • Keep an eye on php.net/supported-versions.php to see which versions still receive fixes.
info
Features are not a goal
A project that uses PHP 8.2 features well is better than one that uses PHP 8.5 syntax badly. Choose clarity first.