PHP 8.5 is here, and while it may not feel quite as dramatic as PHP 8.4’s property hooks and asymmetric visibility, it brings some excellent quality-of-life improvements for everyday PHP developers.
This release focuses on cleaner code, safer APIs, better debugging, improved URL handling, and small but useful syntax improvements.
In this article, we’ll look at the most important PHP 8.5 features with simple examples.
1. The New Pipe Operator
One of the biggest additions in PHP 8.5 is the new pipe operator: |>.
The pipe operator lets you pass the result of one expression into the next function, making transformation code easier to read from left to right.
Before PHP 8.5
$title = ' PHP 8.5 Released ';
$slug = strtolower(
str_replace('.', '',
str_replace(' ', '-',
trim($title)
)
)
);
echo $slug;
PHP 8.5
$title = ' PHP 8.5 Released ';
$slug = $title
|> trim(...)
|> (fn($value) => str_replace(' ', '-', $value))
|> (fn($value) => str_replace('.', '', $value))
|> strtolower(...);
echo $slug;
Why it’s useful
This makes code easier to follow because each step happens in order.
Instead of reading deeply nested function calls from the inside out, you can read the logic from top to bottom.
This is especially useful when cleaning strings, processing arrays, transforming request data, formatting output, or building readable data pipelines.
2. New URI Extension
PHP 8.5 adds a new built-in URI extension for working with URLs and URIs in a more structured way.
For years, PHP developers have often used parse_url(), manual string handling, or third-party packages for more advanced URL work. PHP 8.5 gives us a more modern object-based option.
Before PHP 8.5
$parts = parse_url('https://example.com/blog/php-85');
echo $parts['host'];
PHP 8.5
use Uri\Rfc3986\Uri;
$uri = new Uri('https://example.com/blog/php-85');
echo $uri->getHost();
Why it’s useful
This is useful for web applications, routing, APIs, redirects, crawlers, scrapers, and security-sensitive URL validation.
Working with URLs can become surprisingly messy once you deal with hosts, paths, query strings, fragments, encoded characters, redirects, and edge cases.
Having a proper URI API built into PHP is a very welcome improvement.
3. Clone With
PHP 8.5 introduces a cleaner way to clone an object while changing selected properties.
This is especially helpful for immutable objects and readonly classes.
Example
readonly class UserProfile
{
public function __construct(
public string $name,
public string $email,
public string $role
) {}
public function withRole(string $role): self
{
return clone($this, [
'role' => $role,
]);
}
}
$user = new UserProfile(
name: 'Steve',
email: 'steve@example.com',
role: 'user'
);
$admin = $user->withRole('admin');
echo $admin->role;
Why it’s useful
This makes immutable objects easier to work with.
Instead of manually copying every property into a new object, you can clone the existing object and change only what needs to change.
This is excellent for value objects, DTOs, configuration objects, and clean domain modelling.
For example, if you had a Money, Address, UserProfile, EmailMessage, or AppConfig object, you could create a modified copy without mutating the original object.
4. #[\NoDiscard] Attribute
PHP 8.5 adds a new #[\NoDiscard] attribute.
This tells PHP that the return value of a function should not be ignored. If the function is called and the return value is not used, PHP can warn you.
Example
#[\NoDiscard]
function validateEmail(string $email): bool
{
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
validateEmail('test@example.com');
In this example, the return value is ignored.
That defeats the purpose of calling a validation function.
Correct usage
$isValid = validateEmail('test@example.com');
if ($isValid) {
echo 'Email is valid';
}
Intentionally ignoring the result
(void) validateEmail('test@example.com');
Why it’s useful
This is great for functions where ignoring the return value could cause bugs.
Examples include:
- validation functions
- security checks
- save or update operations
- parsing functions
- result-based service calls
This makes APIs safer and encourages developers to handle important return values properly.
5. array_first() and array_last()
PHP 8.5 adds two small but very useful array helper functions: array_first() and array_last().
These return the first or last value from an array, or null if the array is empty.
Before PHP 8.5
$users = ['Steve', 'Jessica', 'Tony'];
$firstUser = $users[array_key_first($users)];
$lastUser = $users[array_key_last($users)];
echo $firstUser;
echo $lastUser;
PHP 8.5
$users = ['Steve', 'Jessica', 'Tony'];
$firstUser = array_first($users);
$lastUser = array_last($users);
echo $firstUser;
echo $lastUser;
Why it’s useful
This removes boilerplate and makes code easier to understand.
It also works nicely with the null coalescing operator.
$latestEvent = array_last($events) ?? 'No events found';
Simple, clean, and readable.
6. Fatal Errors Now Include Backtraces
PHP 8.5 improves debugging by adding stack trace support for fatal errors.
This is a big win when trying to track down problems in real applications.
Why it’s useful
Fatal errors can be painful, especially when they happen deep inside a codebase.
A backtrace gives you more context about where the problem came from, making debugging faster and less frustrating.
For developers working on large PHP systems, this is one of those features that may not look exciting at first, but it will save time when something breaks.
7. New get_error_handler() and get_exception_handler() Functions
PHP 8.5 adds two new functions:
get_error_handler();
get_exception_handler();
These allow you to inspect the currently registered error and exception handlers.
Why it’s useful
This is handy for frameworks, debugging tools, logging systems, and applications that temporarily replace error handlers.
It gives developers more visibility into how errors and exceptions are being managed.
For example, this can help when debugging applications that use custom error handlers, middleware, framework bootstrapping, or testing tools.
8. Better CLI Configuration Checking
PHP 8.5 adds a useful CLI improvement:
php --ini=diff
This can show non-default INI settings.
Why it’s useful
This is excellent for developers and system administrators.
When working across local, staging, and production environments, configuration differences can cause unexpected bugs.
Being able to quickly see which INI settings differ from the defaults makes PHP environments easier to debug and compare.
For example, it can help answer questions like:
- Why does this work locally but fail on production?
- Is the memory limit different on staging?
- Is error reporting configured differently?
- Are extensions or settings behaving differently between environments?
For anyone managing real-world PHP applications, this is a very practical addition.
9. New max_memory_limit INI Directive
PHP 8.5 introduces a new max_memory_limit directive, which can set a ceiling for memory_limit.
Why it’s useful
This is useful for hosting providers, shared environments, production servers, and systems where you want tighter control over memory usage.
It helps prevent scripts or local configuration changes from raising memory limits beyond an allowed maximum.
For production environments, this is a sensible improvement because memory issues can quickly affect reliability.
10. Closures and First-Class Callables in Constant Expressions
PHP 8.5 also allows static closures and first-class callables in constant expressions.
This can be useful when you want to define reusable behaviour in places that previously could not support it.
Example
function formatName(
string $name,
array $formatters = [
trim(...),
strtolower(...),
]
): string {
foreach ($formatters as $formatter) {
$name = $formatter($name);
}
return $name;
}
echo formatName(' STEVE ');
Why it’s useful
This is more of an advanced feature, but it opens the door for cleaner configuration, attributes, callbacks, and reusable pipelines.
It also works nicely with the broader PHP direction of making functions and callables easier to pass around.
11. Persistent cURL Share Handles
PHP 8.5 adds support for persistent cURL share handles.
This can help avoid repeated setup costs when PHP makes multiple HTTP requests across requests, especially when sharing things like DNS cache and SSL sessions.
Why it’s useful
For many smaller applications, you may never directly touch this feature.
However, for applications that make lots of HTTP requests, API calls, webhooks, crawler requests, or service-to-service calls, this can help improve efficiency.
This is one of those lower-level improvements that framework and library authors may take advantage of before most everyday developers notice it directly.
12. Important Deprecations
Like every PHP release, PHP 8.5 also includes deprecations.
Some of the notable ones include non-canonical scalar casts such as (boolean), (integer), (double), and (binary).
Developers should use (bool), (int), (float), and (string) instead.
Example
// Old style
$isActive = (boolean) $value;
$count = (integer) $number;
// Recommended
$isActive = (bool) $value;
$count = (int) $number;
The backtick operator as an alias for shell_exec() has also been deprecated.
Before
$output = `ls -la`;
Prefer explicit code
$output = shell_exec('ls -la');
Why it matters
Deprecations are warnings about the future.
Your code may still work today, but cleaning these up early makes future upgrades easier.
This is especially important if you maintain older PHP systems, custom CMS projects, WordPress plugins, Laravel applications, legacy business systems, or long-running internal tools.
Other Smaller Improvements
PHP 8.5 also includes several smaller improvements worth knowing about:
- attributes can now target constants
-
#[\Override]can now be applied to properties -
#[\Deprecated]can now be used on traits and constants - static properties now support asymmetric visibility
-
setcookie()andsetrawcookie()now support thepartitionedkey - new DOM methods are available
- new internationalisation improvements have been added
- new PHP build constants are available
These are not always headline features, but they continue PHP’s movement toward cleaner, safer, and more expressive code.
Conclusion
PHP 8.5 is a practical release.
It may not feel as visually dramatic as PHP 8.4, but it brings several improvements that developers will actually use.
The biggest wins are:
- the pipe operator makes transformation code easier to read
- the URI extension improves URL handling
- clone with makes immutable objects easier
-
#[\NoDiscard]helps prevent ignored return values -
array_first()andarray_last()reduce boilerplate - fatal error backtraces improve debugging
- new configuration and error handler tools improve developer experience
Overall, PHP 8.5 continues the modern PHP direction: cleaner syntax, safer code, better tooling, and improved maintainability.
For everyday web developers, this is another solid step forward.
Top comments (0)