Back to all articles
Technology Trends Dec 8, 2025 โˆ™ 1 min read

Exploring New Features in PHP 8.5: A Developer's Guide

Discover the latest updates, features, and improvements in PHP 8.5 with practical examples.

A graphic announcing the release of PHP 8.5, showing the PHP logo and new feature icons.

Exploring the Features of PHP 8.5: A Comprehensive Guide

Discover the latest updates, features, and improvements in PHP 8.5 with practical examples.

The PHP language continues its impressive evolution, with each new version bringing valuable improvements that enhance performance, readability, and developer experience. Scheduled for release in November 2025, PHP 8.5 is set to introduce another exciting round of features, deprecations, and quality-of-life updates. From a long-awaited Pipe Operator to new native array functions, this release is packed with changes that will streamline common coding patterns and make the language even more robust.

For developers in the PHP ecosystem, staying on top of these updates is key to writing modern, efficient, and maintainable code. This guide will provide a comprehensive overview of the most significant features coming in PHP 8.5, complete with practical examples to help you understand how they can be integrated into your development workflow.

The Pipe Operator (|>)

One of the most anticipated features in PHP 8.5 is the introduction of the Pipe Operator. This feature offers an elegant, readable way to chain multiple function calls together, passing the result of one function as the first argument to the next. It’s a native alternative to nested function calls, which can quickly become hard to read.

Currently, if you want to apply a series of transformations to a value, you might write something like this:

$string = "   Hello, world!   ";
$result = htmlspecialchars(strtoupper(trim($string)));
echo $result; // "HELLO, WORLD!"

This code is read from the inside out, which can feel unnatural. The Pipe Operator reverses this, allowing you to write the same logic in a clear, left-to-right sequence.

// With the Pipe Operator in PHP 8.5
$string = "   Hello, world!   ";
$result = $string |> trim(...) |> strtoupper(...) |> htmlspecialchars(...);
echo $result; // "HELLO, WORLD!"

The pipe operator takes the value on its left and passes it as the first argument to the function on its right. The ... placeholder signifies where the value is being passed. This syntax makes complex data transformations much more intuitive and maintainable.

Native array_first() and array_last() Functions

For years, developers have relied on user-land solutions or a combination of functions like reset(), end(), and array_key_first() to get the first or last value from an array. These methods often had side effects, like modifying the array's internal pointer, or were simply cumbersome.

PHP 8.5 finally introduces native array_first() and array_last() functions to solve this common problem cleanly.

The function signatures are:

// Fetches the first value of an array
array_first(array $array, ?callable $callback = null, mixed $default = null): mixed

// Fetches the last value of an array
array_last(array $array, ?callable $callback = null, mixed $default = null): mixed

Basic Usage

Here’s how you can use them to get the first and last elements of a simple array:

$numbers = [10, 20, 30, 40, 50];

$first = array_first($numbers); // 10
$last = array_last($numbers);   // 50

Advanced Usage with a Callback

These functions also accept an optional callback to find the first or last element that satisfies a specific condition. This is a powerful alternative to looping through an array yourself.

$users = [
    ['name' => 'Alice', 'role' => 'editor'],
    ['name' => 'Bob', 'role' => 'admin'],
    ['name' => 'Charlie', 'role' => 'admin'],
    ['name' => 'Diana', 'role' => 'guest'],
];

// Find the first user who is an admin
$firstAdmin = array_first($users, fn($user) => $user['role'] === 'admin');
// Returns: ['name' => 'Bob', 'role' => 'admin']

// Find the last user who is an admin
$lastAdmin = array_last($users, fn($user) => $user['role'] === 'admin');
// Returns: ['name' => 'Charlie', 'role' => 'admin']

// Provide a default value if no match is found
$subscriber = array_first($users, fn($user) => $user['role'] === 'subscriber', 'No subscriber found');
// Returns: 'No subscriber found'

A New, Modern URI Extension

Parsing and manipulating URIs has always been a bit tricky in PHP. The existing parse_url() function has known inconsistencies and doesn't fully comply with modern standards like RFC 3986.

PHP 8.5 introduces a new, standards-compliant uri extension that provides a robust and reliable way to work with URIs. This extension is always available, providing a consistent API for developers.

Here is an example demonstrating the new Uri class:

use Bcremer\Uri\Uri;

$uriString = 'https://user:pass@example.com:8080/path?query=value#fragment';
$uri = new Uri($uriString);

echo $uri->getScheme();    // "https"
echo $uri->getAuthority(); // "user:pass@example.com:8080"
echo $uri->getUserInfo();  // "user:pass"
echo $uri->getHost();      // "example.com"
echo $uri->getPort();      // 8080
echo $uri->getPath();      // "/path"
echo $uri->getQuery();     // "query=value"
echo $uri->getFragment();  // "fragment"

// You can also modify parts of the URI immutably
$newUri = $uri->withScheme('http')->withPort(null);
echo $newUri; // "http://user:pass@example.com/path?query=value#fragment"

This new extension provides a much-needed modern foundation for handling URIs in PHP applications.

Recursive Closures with Closure::getCurrent()

Previously, creating a recursive anonymous function (a closure that calls itself) required a clunky workaround where you had to pass the closure into itself by reference.

// The old way
$factorial = null;
$factorial = function(int $n) use (&$factorial): int {
    if ($n <= 1) {
        return 1;
    }
    return $n * $factorial($n - 1);
};

PHP 8.5 simplifies this with the Closure::getCurrent() static method, which returns the currently executing closure.

// The new way in PHP 8.5
$factorial = function(int $n): int {
    if ($n <= 1) {
        return 1;
    }
    return $n * Closure::getCurrent()($n - 1);
};

echo $factorial(5); // 120

This makes the intent of the code clearer and removes the need for the "use by reference" boilerplate.

Backtraces for Fatal Errors

Fatal errors, such as those caused by syntax mistakes or calling an undefined function, can be frustrating to debug because they often don't provide a backtrace. PHP 8.5 changes this by introducing the fatal_error_backtraces INI setting, which is enabled by default.

With this feature, you will now get a full stack trace for fatal errors, making it much easier to pinpoint the exact location and context of the problem without needing to rely on external tools like Xdebug.

Other Notable Features

  • Closures in Constant Expressions: It is now possible to use closures in places where constant expressions are allowed, such as default property values, static variables, and attribute arguments.
  • INI Diff Option (--ini --diff): A new --diff flag for the php --ini command allows you to see only the INI settings that have been changed from their default values, making it easier to audit your PHP configuration.

Preparing for PHP 8.5

PHP 8.5 is scheduled for General Availability (GA) on November 20, 2025. Between now and then, there will be several Release Candidates (RCs) that provide an opportunity for the community to test the new version and report any issues.

To prepare for the upgrade, developers should:

  1. Consult the Deprecation List: Review the official list of deprecations for PHP 8.5 on the PHP Wiki to identify any features your application uses that will be removed or changed.
  2. Test Early: Once the first Release Candidate is available, test your applications in a staging environment. This will help you catch any compatibility issues early.
  3. Update Dependencies: Ensure your project's dependencies are compatible with PHP 8.5. Keep an eye on announcements from major frameworks and libraries like Laravel and Symfony.

Conclusion

PHP 8.5 continues the language's forward momentum, delivering features that prioritize developer experience, code readability, and robustness. The Pipe Operator will undoubtedly change how we write data transformations, while native array_first() and array_last() functions provide a clean solution to a long-standing problem. Combined with the new URI extension and improved debugging capabilities, this release offers tangible benefits for developers across the ecosystem.

By staying informed and preparing for the upgrade, you can leverage these new features to build better, faster, and more maintainable PHP applications.


Related articles

Continue exploring Laravel insights and practical delivery strategies.

Laravel consulting

Need senior Laravel help for this topic?

Let's adapt these practices to your product and deliver the next milestone.