PHP 8.5 is scheduled to drop on November 20, 2025, bringing significant improvements that'll make PHP developers everywhere smile. This release focuses on three key areas: making your code more readable, boosting efficiency, and simplifying debugging. Let's explore the standout features in PHP 8.5, including brand-new array functions like array_first and array_last, the long-awaited pipe operator (|>), support for closures and first-class callables in constant expressions, plus helpful new functions get_error_handler and get_exception_handler.
Top Features in PHP 8.5
PHP 8.5 introduces a collection of powerful features that'll transform how PHP developers write code. Here's what every PHP developer should know about this exciting release.
New Array Functions
The array_first and array_last functions in PHP 8.5 let you grab the first or last element from arrays in a much cleaner and safer way, without messing with the array's internal pointer. This solves the headaches caused by older methods like reset() or end(), which could break array iterators.
How array_first() and array_last() Work
Both functions handle associative and numeric arrays seamlessly, and they automatically dereference elements that are references.
// Examples with array numeric
$fruits = ['apple', 'banana', 'orange'];
echo array_first($fruits); // 'apple'
echo array_last($bfruits); // 'orange'
// Examples with array associative
$data = ['name' => 'John Dev', 'age' => 25, 'City' => 'New York'];
echo array_first($data); // 'John Dev'
echo array_last($data); // 'New York'
// Empty Array
$emptyArray = [];
echo array_first($emptyArray) ?? 'Array is Empty';
echo array_last($emptyArray) ?? 'Array is Empty';
// Array with random key orders
$randomArray = [1 => 'a', 0 => 'b', 3 => 'c', 2 => 'd'];
echo array_first($randomArray); // 'a'
echo array_last($randomArray); // 'd'
Understanding array_first() and array_last()
array_first(array $array): mixed: Returns the first value from an array based on key order (not numeric index). Returns null for empty arrays .array_last(array $array): mixed: Returns the last value from an array. Just like array_first(), it returns null for empty arrays .
These functions work consistently with existing functions like array_key_first() and array_key_last() (introduced in PHP 7.3), but they return values directly instead of keys. They reduce boilerplate code and avoid iterator modifications that could cause bugs in complex code. Plus, they return null for empty arrays, making error handling simple with the null coalescing operator (??).
Pipe Operator
The pipe operator (|>) is one of the most anticipated features in PHP 8.5, enabling linear function chaining that makes your code incredibly readable. This operator passes values from the left side to functions on the right as the first parameter, similar to functional programming languages like Elixir .
Using the Pipe Operator
// without Pipe Operator
$result = trim(str_shuffle(strtoupper('Hello World')));
// with Pipe Operator
$result = 'Hello World'
|> strtoupper(...)
|> str_shuffle(...)
|> trim(...);
// mixing callable example
$result = 'Hello World'
|> 'strtoupper' // String callable
|> fn($x) => trim($x) // Arrow function
|> new MyTrimmer() // __invoke class
|> [Trimmer::class, 'trimStatic']; // Static method
// Class
class MyTrimmer {
public function __invoke($str) { return trim($str); }
}
class Trimmer {
public static function trimStatic($str) { return trim($str, ' '); }
}
How the Pipe Operator Works
- The syntax is value
|> function(...), where indicates a first-class callable. The operator evaluates from left to right and can be chained multiple times . - Each function must have at least one parameter (or can have none, but it'll be ignored). By-reference parameters aren't allowed, except for certain built-in functions.
- Type coercion follows PHP's standard rules, so if
strict_types=1, you might trigger TypeError exceptions. - The code gets optimized during compilation into opcode similar to nested structures, with memory-efficient copy-on-write handling.
Support for Closures and First-Class Callables in Constant Expressions
PHP 8.5 introduces support for static closures and first-class callables as default values in constants, class properties, and function arguments. This makes code more expressive without needing nullable type hints for optional callbacks.
Using Closures and First-Class Callables in Constants
// constant class
class Config {
const DEFAULT_FILTER = static fn($value) => trim(strip_tags($value));
}
// property class
class Processor {
private array $callbacks = [
static fn($val) => strtoupper($val),
Processor::sanitize(...)
];
private static function sanitize($val) { return htmlspecialchars($val); }
}
function process(string $input, callable $filter = static fn($x) => $x) {
return $filter($input);
}
echo process('Hello'); // 'Hello'
echo Config::DEFAULT_FILTER('<b>World</b>'); // 'World'
Understanding Closures in Constant Expressions
- Supported Contexts: You can use these in global or class constants, class properties (static/non-static), and function default arguments.
- Only static closures with
static fnandstaticmethods are supported, since constants must be evaluated at compile time. - Non-static closures aren't supported because they depend on
$thisor instance variables. - This reduces the need for null as default callbacks, making code safer and cleaner.
get_error_handler() and get_exception_handler()
These two new functions in PHP 8.5 provide direct access to active error and exception handlers, making debugging and dynamic error management much easier.
Using get_error_handler() and get_exception_handler()
// set handler
set_error_handler(function($errno, $errstr) { echo "Error: $errstr"; });
set_exception_handler(function($e) { echo "Exception: " . $e->getMessage(); });
// get handler
var_dump(get_error_handler());
var_dump(get_exception_handler());
// examples
if (get_error_handler() === null) {
echo "no error handler.";
}
Understanding the New Handler Functions
get_error_handler(): ?callable: Returns the current error handler from set_error_handler(), or null if none exists .get_exception_handler(): ?callable: Returns the current exception handler from set_exception_handler(), or null if none exists .
These functions allow handler inspection without modification, which is perfect for libraries or frameworks that need to check error configuration.
The Bottom Line
The new features in PHP 8.5 bring fresh efficiency to PHP developers everywhere. With the detailed PHP 8.5 code examples above, you can start experimenting with the beta version for your latest projects.
These improvements represent PHP's continued evolution toward more readable, efficient, and developer-friendly code. The pipe operator alone will change how many developers approach function composition, while the new array functions eliminate common pain points that have frustrated PHP developers for years.
Thanks for reading!
