Milind Daraniya

PHP 8.5 Is More Than a Version Upgrade: What Has Changed for Laravel Developers

Published September 7th, 2026 24 min read

When someone says:

"Just upgrade PHP."

it sounds very easy.

Change the PHP version.

Run Composer.

Run the tests.

Deploy.

Done.

In real projects, it is usually not that simple.

I have worked on enough Laravel applications to know that a PHP upgrade can affect much more than the PHP runtime itself.

It can affect:

Laravel
Composer
Packages
Extensions
Database drivers
Queue workers
Cron jobs
CLI commands
Docker
Production servers

And now PHP 8.5 is part of that conversation.

PHP 8.5 was released on November 20, 2025, and it introduced several language-level improvements, including the pipe operator, the URI extension, clone() with property updates, array_first(), array_last() and the #[\NoDiscard] attribute. PHP 8.5 remains under active support, with security support scheduled through the end of 2029.

Laravel 13 was released on March 17, 2026 and supports PHP 8.3 through 8.5.

For me, the interesting question is not:

"What new syntax did PHP add?"

The better question is:

"What do these changes mean for developers building real Laravel applications?"

PHP has changed much more than people think

Sometimes I still hear people describe PHP as if it is the same language from ten or fifteen years ago.

I don't think that picture is accurate anymore.

Modern PHP has:

Typed properties
Union types
Enums
Attributes
Readonly classes
Fibers
First-class callables
Better error handling
Better type safety
Improved performance

And now PHP 8.5 adds another group of features.

The language is becoming more expressive while still keeping the productivity that made PHP so popular for web development.

That is one reason I still enjoy working with it.

The pipe operator is probably the most visible new feature

One of the new PHP 8.5 features is the pipe operator:

|>

It allows a value to move through a sequence of callable operations from left to right. PHP's official release documentation shows it as a way to make chained transformations easier to read.

For example, older PHP code can sometimes become difficult to read when functions are nested:

$result = strtolower(
    str_replace(
        '.',
        '',
        str_replace(
            ' ',
            '-',
            trim($title)
        )
    )
);

The problem isn't that this code is impossible to understand.

The problem is that the order of operations is visually reversed.

I have to read from the inside out.

With the pipe operator, the same idea can be written more like the way I naturally think about the operation:

$result = $title
    |> trim(...)
    |> (fn ($value) => str_replace(' ', '-', $value))
    |> (fn ($value) => str_replace('.', '', $value))
    |> strtolower(...);

Now I can read it from top to bottom.

First trim.

Then replace spaces.

Then remove dots.

Then lowercase.

That is much easier to follow.

This could be useful in data transformation code

This is where I think the pipe operator has real practical value.

Laravel applications do a lot of data transformation.

For example:

Request
↓
Normalize
↓
Validate
↓
Transform
↓
Format
↓
Store

We often implement this with helper functions, service classes or collections.

The pipe operator gives PHP another way to express a sequence of transformations.

I don't think it replaces Laravel Collections.

It simply gives the language another useful way to express sequential operations.

But developers can also abuse the pipe operator

This is important.

New syntax always creates the temptation to use it everywhere.

I don't want code like:

$value
    |> something(...)
    |> somethingElse(...)
    |> anotherThing(...)
    |> anotherThing(...)
    |> anotherThing(...);

if a clear service method would explain the business logic better.

The goal is not:

"Use the newest PHP feature."

The goal is:

"Make the code easier to understand."

If the pipe operator improves readability, use it.

If it makes the code harder to understand, don't.

The new URI extension is also interesting

PHP 8.5 adds a built-in URI extension for parsing and handling URIs according to modern URL standards.

This matters more than it may initially sound.

Web applications deal with URLs constantly.

Laravel applications especially deal with:

Routes
Query strings
Redirect URLs
Callback URLs
Webhook URLs
OAuth URLs
API URLs
External service URLs

Historically, developers have used a mixture of PHP functions, framework helpers and third-party libraries for URL-related work.

Having a more capable native URI API gives PHP developers a stronger standard-library option.

This matters for API-heavy applications

Modern SaaS applications integrate with many external services.

Imagine:

Razorpay
PayU
Google
Meta
Microsoft
AWS
Internal APIs
Third-party SaaS

Every integration has URLs.

Some have:

Query parameters
Fragments
Paths
Ports
Hosts
Schemes

A proper URI abstraction is useful when applications need to safely parse and construct these values.

This is one of those features that may not look exciting in a demo but can become useful in real backend code.

clone() becomes more useful

PHP 8.5 also introduces a new way to clone an object while changing selected properties during the clone operation.

Conceptually:

$newObject = clone($object, [
    'status' => 'processed',
]);

This can be useful when working with immutable-style objects.

Instead of:

$new = clone $object;
$new->status = 'processed';

we can express the intent directly.

This becomes especially interesting when using:

Readonly classes
Immutable value objects
DTOs
Domain objects
Configuration objects

Immutable thinking is becoming more useful in PHP

This is something I personally like.

As applications become more complex, mutable state can create bugs.

Suppose a service receives an object.

Then somewhere inside the service, another method changes the same object.

Now another part of the application sees the modified value.

These bugs can become difficult to understand.

Immutable-style objects reduce that risk.

PHP has been moving toward stronger support for immutable programming patterns, and clone() with property updates is another small step in that direction.

array_first() and array_last() look small, but small features matter

PHP 8.5 adds:

array_first()
array_last()

These return the first or last value of an array and return null when the array is empty.

Some developers may look at this and say:

"Why do we need another helper?"

But this is exactly the type of small improvement that removes repetitive code.

Before:

$last = $items === []
    ? null
    : $items[array_key_last($items)];

Now:

$last = array_last($items);

That is easier to read.

Not every important language improvement has to be revolutionary.

Sometimes removing tiny pieces of boilerplate makes everyday development nicer.

PHP is slowly moving more utility code into the core language

This is something I notice when looking at modern PHP.

Developers historically relied heavily on:

Framework helpers
Third-party packages
Custom utility classes
Small helper functions

Some of that remains useful.

But the language itself is becoming more capable.

That is healthy.

Because common programming tasks should not always require another dependency.

And fewer dependencies can also mean:

Less maintenance
Less security risk
Less compatibility problems
Less deployment complexity

#[\NoDiscard] is another interesting feature

PHP 8.5 introduces the #[\NoDiscard] attribute. It can warn developers when a function's returned value is ignored.

At first, this sounds very small.

But think about functions where ignoring the result is a bug.

For example:

$result = importantOperation();

What if somebody later changes it to:

importantOperation();

and the result is actually required?

The compiler or static-analysis tooling can help catch that kind of mistake.

This fits a larger trend I like:

Push more mistakes toward development time instead of production time.

Modern PHP is becoming more explicit

This is one of the larger changes I have noticed over the years.

Old PHP code often relied heavily on conventions and dynamic behavior.

Modern PHP increasingly encourages:

Types
Attributes
Enums
Readonly
Explicit APIs
Better static analysis

This makes PHP more comfortable for large codebases.

And for me, that is important.

Because a language used for a small website and a language used for a 500,000-line SaaS application have different requirements.

Large applications need stronger contracts.

This is where Laravel fits nicely

Laravel has always made PHP productive.

We get:

Routing
Validation
Eloquent
Queues
Jobs
Events
Policies
Authentication
Notifications
Caching

Then modern PHP provides the language-level features underneath.

So the combination becomes:

Modern PHP
+
Modern Laravel
=
Productive backend development

I don't think developers should separate the two discussions.

Laravel benefits from the language becoming stronger.

Laravel 13 makes the timing interesting

Laravel 13 was released in March 2026 and supports PHP 8.3, 8.4 and 8.5. Its release continues Laravel's annual release cycle, so PHP version planning is becoming an increasingly normal part of Laravel upgrade planning.

This is important for real projects.

A Laravel upgrade is not always just:

composer require laravel/framework

We also need to think about:

PHP version
Composer
Extensions
Packages
Server configuration
CLI version
PHP-FPM version
Queue workers
Cron jobs
Docker image
CI environment

This is where upgrades become engineering work rather than simply a composer command.

PHP version consistency matters

I have seen this type of problem many times.

Local machine:

PHP 8.4

Server:

PHP 8.2

Composer:

Different environment

Queue worker:

Different PHP binary

Now something works locally but fails in production.

This is why I prefer checking:

php -v
composer check-platform-reqs

and making sure CLI and web-server PHP versions are actually aligned.

Laravel 13 requires PHP 8.3 or newer, so this consistency becomes especially important when upgrading older applications.

"It works in the browser" is not enough

A Laravel application can use several different PHP execution environments.

For example:

Nginx
↓
PHP-FPM

and separately:

CLI
↓
PHP

and:

Queue Worker
↓
PHP

and:

Cron
↓
PHP

They need to be compatible.

A common upgrade mistake is updating PHP-FPM but forgetting the CLI version.

Then:

php -v

shows one version while the web application runs another.

This can create very confusing Composer and Artisan problems.

Composer is part of the upgrade

A PHP upgrade can change what Composer is allowed to install.

For example:

PHP 8.2

may allow one dependency set.

Then:

PHP 8.5

may allow a newer dependency set.

This means upgrading PHP can indirectly change the package graph.

That is why I like upgrading deliberately.

First inspect.

Then test.

Then update dependencies.

Then test again.

Not:

composer update

and hope for the best.

Production servers are where upgrades become real

Local PHP 8.5 is easy.

Production PHP 8.5 is another story.

We need to think about:

PHP-FPM
Nginx
Extensions
OPcache
Redis
MySQL driver
Supervisor
Cron
Queue workers
SSL
Monitoring
Logs

A production upgrade should be treated like a deployment.

Not like:

"Install a new PHP package."

PHP extensions matter too

This is something that often gets forgotten.

Our application might depend on:

pdo_mysql
redis
mbstring
intl
curl
openssl
zip
gd
imagick

A new PHP version may require checking whether every extension is available and compatible.

Laravel itself has required PHP extensions, and production deployment documentation lists these requirements explicitly.

A working PHP runtime without the required extensions is still a broken Laravel environment.

PHP 8.5 is also a reason to clean old code

I don't like doing version upgrades only as:

Old code
↓
New PHP

I prefer using the upgrade as an opportunity to review:

Deprecated syntax
Old helpers
Unused packages
Custom hacks
Type assumptions
Legacy error handling

PHP 8.5 includes several deprecations and backward-compatibility changes, including deprecations around older cast forms and certain other legacy behaviors.

This gives us a good reason to clean up code that has been carried forward for years.

Don't upgrade because someone says "newer is faster"

This is another lesson I keep coming back to.

New PHP versions can bring improvements.

But performance is application-specific.

If the application is slow because:

Bad SQL
Missing index
N+1
External API
Memory problem
Poor caching

then simply moving from PHP 8.4 to PHP 8.5 may not solve the actual problem.

We should still profile the real application.

The correct sequence is:

Measure
↓
Find bottleneck
↓
Change
↓
Measure again

Not:

Upgrade
↓
Hope

The PHP ecosystem is becoming more modern without losing productivity

This is probably my main takeaway.

A lot of developers think stronger type systems, better language features and modern runtimes automatically mean:

"More complicated code."

It doesn't have to.

If used properly, these features can make code simpler.

For example:

Pipe operator
→ cleaner transformations

array_first()
→ less boilerplate

clone()
→ clearer immutable updates

NoDiscard
→ fewer ignored results

URI extension
→ stronger URL handling

These are mostly small improvements.

But thousands of small improvements can change the developer experience significantly.

Should Laravel developers move to PHP 8.5?

I think the answer depends on the application.

For a new Laravel project:

I would seriously consider PHP 8.5.

For an older production project:

I would first check:

Laravel version
Package compatibility
PHP extensions
Deployment environment
Tests
Third-party integrations
Queue workers

Then upgrade in a controlled way.

The PHP project currently lists PHP 8.5 as actively supported, while PHP 8.4 is scheduled to move out of active support at the end of 2026.

That makes PHP 8.5 a sensible long-term target for teams planning upgrades now.

What I would do in a real Laravel project

My upgrade process would roughly be:

Current PHP version
↓
Check Laravel support
↓
Check composer.json
↓
Check package compatibility
↓
Create upgrade branch
↓
Upgrade local PHP
↓
Run tests
↓
Fix deprecations
↓
Update Composer dependencies
↓
Test queues
↓
Test scheduled jobs
↓
Test APIs
↓
Test integrations
↓
Deploy staging
↓
Monitor
↓
Production

The important point is that PHP is only one part of the system.

I would also test long-running processes

This becomes particularly important if the application uses:

Laravel Octane
Queue workers
Workers
WebSockets
Long-running processes

A request that works correctly in a traditional PHP-FPM lifecycle should still be tested under a long-running runtime.

This is where language upgrades and runtime architecture can interact.

PHP 8.5 also tells us something about the future

We are already seeing PHP 8.6 development builds in 2026, while PHP 8.5 continues to receive regular updates.

That means the PHP project is continuing its regular evolution.

PHP is not standing still.

And I think developers should pay attention to that.

Not every release changes how we build applications.

But the direction matters.

The language is becoming:

More typed
More expressive
More explicit
More standardized
More developer-friendly

without abandoning its traditional strength:

Fast application development.

My biggest lesson from PHP upgrades

A PHP version upgrade is not really about PHP.

It is about the entire application environment.

When I upgrade:

PHP

I am really touching:

Application
+
Framework
+
Composer
+
Extensions
+
Server
+
Workers
+
CI/CD
+
Deployment

That is why production upgrades need planning.

My final view

I don't think PHP 8.5 is a revolutionary release that suddenly changes everything.

And that is actually fine.

I don't need every release to completely reinvent the language.

What I like is the direction.

Small language improvements.

Better standard-library capabilities.

Cleaner syntax.

More explicit code.

Better developer tooling.

And better support for building large applications.

For someone like me who spends a lot of time with Laravel and SaaS applications, PHP 8.5 is not something I want to ignore.

I don't need to use every new feature immediately.

I don't need to rewrite working code.

I simply want to understand what the new version gives me and where it can make my code better.

Because in the end, the goal of a PHP upgrade should not be:

"We are using the latest PHP."

The goal should be:

"Our application is easier to maintain, safer to operate and ready for the next few years."

That is a much better reason to upgrade.