The PHP 8.5 features worth knowing for Laravel developers include the pipe operator (|>), clone() with property updates for readonly classes, the #[\NoDiscard] attribute, the array_first() and array_last() functions, and the built-in URI extension. PHP 8.5 was released on November 20, 2025, and Laravel 13 supports it.

Many developers upgrade PHP for security updates but never use the new syntax. That’s a missed opportunity. Several PHP 8.5 features can eliminate boilerplate you write regularly, including nested function calls, custom withX() methods, and the $array[array_key_last($array)] pattern.

This guide covers the key PHP 8.5 features with before-and-after examples, explains where they fit into Laravel applications, and lists the deprecations to check before upgrading.

Key Takeaways

  • PHP 8.5 was released on November 20, 2025. It receives active support until December 31, 2027, and security fixes until December 31, 2029.

  • Laravel 13 supports PHP 8.3–8.5, while Laravel 12 supports PHP 8.2–8.5. You can upgrade PHP without upgrading Laravel first.

  • The pipe operator makes nested function calls easier to read, while clone() with an array of property updates simplifies immutable objects.

  • array_first() and array_last() can work in Laravel 13 apps on PHP 8.3 and 8.4 through a Symfony polyfill.

  • Check deprecations before upgrading. Backtick shell execution, (integer)-style casts, and null array offsets now trigger deprecation notices.

PHP 8.5 Release Date and Laravel Support

PHP 8.5 was released on November 20, 2025. Here’s how it compares with the PHP versions commonly used by Laravel applications, according to PHP’s supported versions page.

PHP version

Released

Active support until

Security fixes until

8.3

Nov 23, 2023

Dec 31, 2025 (ended)

Dec 31, 2027

8.4

Nov 21, 2024

Dec 31, 2026

Dec 31, 2028

8.5

Nov 20, 2025

Dec 31, 2027

Dec 31, 2029

On the Laravel side, Laravel 13 supports PHP 8.3, 8.4, and 8.5. Laravel 12 supports PHP 8.2 through 8.5, according to the Laravel 13 release notes.

Laravel 12 is now receiving security fixes only. Bug fixes ended on August 13, 2026, and security support ends on February 24, 2027.

If you’re running PHP 8.3, its active support has ended, making PHP 8.5 a sensible next step.

1. The Pipe Operator (|>)

The pipe operator is one of the most noticeable PHP 8.5 features. It passes a value through a sequence of callables from left to right. Instead of reading nested function calls from the inside out, you can follow the transformation from top to bottom.

Adapted from the official PHP example:

$title = ' PHP 8.5 Released ';

// PHP 8.4 and older
$slug = strtolower(
    str_replace('.', '',
        str_replace(' ', '-',
            trim($title)
        )
    )
);

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

Where it fits in Laravel: Laravel already provides fluent APIs through collections and Str::of(). The pipe operator is useful for plain PHP values and small custom functions, such as normalizing input before validation.

$email = (string) $request->input('email')
    |> trim(...)
    |> strtolower(...)
    |> (fn (string $email) => filter_var($email, FILTER_VALIDATE_EMAIL) ?: null);

Remember two rules: first-class callables use the name(...) syntax, and arrow functions used in a pipe must be wrapped in parentheses.

2. Clone With: Simpler Readonly Classes

PHP 8.5 lets you update properties while cloning an object by passing an array to clone(). This simplifies the “with” pattern for readonly classes, which are common for DTOs and value objects in Laravel applications, whether you write them yourself or use packages such as Spatie Laravel Data.

Official example from 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);
$transparentBlue = $blue->withAlpha(128);

Before PHP 8.5, a method like withAlpha() typically had to copy every property using get_object_vars() and reconstruct the object.

A Laravel example might be a price quote in a checkout service:

readonly class PriceQuote
{
    public function __construct(
        public int $amountCents,
        public string $currency,
        public ?string $couponCode = null,
    ) {}

    public function withCoupon(string $code, int $discountCents): self
    {
        return clone($this, [
            'couponCode' => $code,
            'amountCents' => $this->amountCents - $discountCents,
        ]);
    }
}

One important rule: clone() can modify readonly properties only from within the class. Calling clone($quote, ['amountCents' => 0]) from a controller throws an error, keeping the value object in control of its own state.

3. #[\NoDiscard]: Catch Ignored Return Values

Add #[\NoDiscard] to a function to make PHP warn when its return value is ignored. If you intentionally want to discard the result, cast the call to (void).

Official example from PHP:

#[\NoDiscard]
function getPhpVersion(): string
{
    return 'PHP 8.5';
}

getPhpVersion();
// Warning: The return value of function getPhpVersion() should
// either be used or intentionally ignored by casting it as (void)

This is useful for service methods where ignoring the result is likely to be a bug. Examples include a method that returns a refund result you need to check or an immutable object's with method that returns a new instance instead of modifying the existing one.

Faisal, a backend lead at a 20-person payments startup in Dubai, added #[\NoDiscard] to the withX() methods on the team’s money and invoice value objects after upgrading in early 2026.

The first test run flagged three places where developers had called $invoice->withDueDate(...) and discarded the returned object. As a result, the due dates were never updated. All three bugs had passed code review.

Faisal is an illustrative composite based on common upgrade scenarios.

Starting a new Laravel project on PHP 8.5? StackMivo generates complete Laravel 13 apps from a plain-English description, so you can spend more time building features and less time writing boilerplate.

4. array_first() and array_last()

These two small functions remove a surprising amount of boilerplate. Both return null when given an empty array, so they work well with the null coalescing operator (??).

Official example from PHP:

// PHP 8.4 and older
$lastEvent = $events === []
    ? null
    : $events[array_key_last($events)];

// PHP 8.5
$lastEvent = array_last($events);

Laravel note: Laravel 13 depends on symfony/polyfill-php85, which provides these functions on PHP versions below 8.5.

This means you can use them in a Laravel 13 application running PHP 8.3 or 8.4. However, there’s one catch: the older laravel/helpers package also defines an array_first() function that accepts a callback.

The native PHP function doesn’t accept that callback. Use Arr::first($array, $callback) when you need to find an element that meets a condition.

See the Laravel 13 upgrade guide for details.

5. The Built-In URI Extension

PHP 8.5 includes an always-available URI extension that parses and modifies URLs according to RFC 3986 and the WHATWG URL standard. It provides a standards-based alternative to parse_url(), which has known edge cases.

Official example from PHP:

use Uri\Rfc3986\Uri;

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

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

In Laravel: Continue using Laravel’s fluent Uri::of() helper when building or modifying URLs in application code.

The new PHP extension is particularly useful when validating or normalizing untrusted URLs, such as webhook endpoints or user-submitted links, where standards-compliant parsing matters.

6. Closures in Constant Expressions

PHP 8.5 allows static closures and first-class callables in constant expressions. These can be used in attribute arguments, default property and parameter values, and constants.

This opens the door to attributes that carry executable logic instead of just strings or other simple values.

Official example from PHP:

final class PostsController
{
    #[AccessControl(static function (
        Request $request,
        Post $post,
    ): bool {
        return $request->user === $post->getAuthor();
    })]
    public function update(
        Request $request,
        Post $post,
    ): Response {
        // ...
    }
}

Laravel’s built-in attributes currently use plain values, but packages and custom attributes can now accept closures. Expect this PHP 8.5 feature to appear in authorization, validation, and routing packages over time.

Smaller PHP 8.5 Features Worth Knowing

PHP 8.5 also introduces several smaller improvements worth knowing about:

  • Backtraces on fatal errors: Errors such as exceeding the maximum execution time now include a backtrace, making slow web requests easier to debug.

  • final in constructor property promotion: You can write public function __construct(final public string $id) {}.

  • More attribute support: #[\Override] can be used on properties, while #[\Deprecated] can be used on traits and constants.

  • Asymmetric visibility for static properties: PHP extends the PHP 8.4 feature to static properties.

  • Closure::getCurrent(): Provides access to the currently executing closure, including for recursion.

  • Persistent cURL share handles: curl_share_init_persistent() can reuse DNS and connection data across requests.

  • Partitioned cookies: A new "partitioned" option is available for setcookie().

For the complete list of new features and changes, see the official PHP 8.5 migration guide.

PHP 8.5 Deprecations to Check in Your Laravel App

Most of the following changes produce deprecation notices in logs and tests. Two are exceptions: __sleep() and __wakeup() are soft-deprecated and do not yet emit notices, while the disable_classes setting has been removed entirely.

Change

What to do

Backtick operator as an alias for shell_exec()

Use shell_exec() or Laravel’s Process facade

(boolean), (integer), (double), and (binary) casts

Use (bool), (int), (float), and (string)

null as an array offset or in array_key_exists()

Use an empty string or check for null first

case statements ending with ;

End them with :

__sleep() and __wakeup() (soft-deprecated, no notice yet)

Plan a move to __serialize() and __unserialize()

disable_classes INI setting (removed)

Remove it from php.ini

PHP 8.5 also introduces warnings when casting NAN, destructuring non-arrays, and casting floating-point values that cannot be represented as integers.

Inga, a freelance Laravel developer in Porto, upgraded a client’s Laravel 12 application to PHP 8.5 in one afternoon in March 2026. The application itself needed no changes. Her test logs showed 40 deprecation notices, all coming from two older packages that used (integer) casts and null array offsets.

She updated one package and opened an issue on the other, keeping production clean.

Inga is an illustrative composite based on common upgrade scenarios.

How to Upgrade a Laravel App to PHP 8.5

  1. Check your Laravel version. Laravel 12 and 13 both support PHP 8.5.

  2. Install PHP 8.5 locally. Laravel Herd makes switching PHP versions for individual projects simple.

  3. Run composer update. Check for packages that do not yet support PHP 8.5.

  4. Run your test suite with deprecation notices enabled. Fix the issues listed above. For larger codebases, Rector and AI refactoring tools can help apply mechanical changes across the project.

  5. Upgrade CI and staging before production. Confirm that your hosting provider offers PHP 8.5 before deploying.

For more about what’s coming next across the ecosystem, see our roundup of Laravel trends for 2026.

Frequently Asked Questions

When was PHP 8.5 released?

PHP 8.5 was released on November 20, 2025. It receives active support until December 31, 2027, and security fixes until December 31, 2029.

What are the main PHP 8.5 features?

The main features include the pipe operator (|>), clone() with property updates, the #[\NoDiscard] attribute, array_first() and array_last(), a built-in URI extension, closures in constant expressions, and persistent cURL share handles.

Does Laravel support PHP 8.5?

Yes. Laravel 13 supports PHP 8.3, 8.4, and 8.5. Laravel 12 supports PHP 8.2 through 8.5.

Should I upgrade my Laravel app to PHP 8.5?

If you’re running PHP 8.3, upgrading is worth considering because its active support ended on December 31, 2025. Run your tests with deprecation notices enabled, update any affected packages, and deploy through staging before production.

Can I use array_first() on PHP 8.4 in Laravel?

Yes, in Laravel 13. Laravel depends on Symfony’s PHP 8.5 polyfill, which provides array_first() and array_last() on older PHP versions.

The Bottom Line

PHP 8.5’s features may look small individually, but they can make a noticeable difference in a Laravel codebase. The pipe operator simplifies data transformations, clone() makes readonly value objects easier to work with, #[\NoDiscard] helps catch ignored return values, and array_first() and array_last() reduce array-handling boilerplate.

Upgrade in staging, resolve deprecation notices, and start using one new feature per pull request. Within a month, these improvements can become a natural part of your workflow.

Generate a Laravel 13 app with StackMivo and start free →