PHP 8.5 is released with the pipe operator, URI extension, new array functions, and more
Last updated on by Paul Redmond
The PHP team has released PHP v8.5 with the Pipe operator, a URI extension, array_first() and array_last() functions, an INI diff flag, and more:
- PHP Pipe Operator
- Native array_first() and array_last() Functions
- A New PHP URI Extension
- Retrieve the Currently Executing Closure
- PHP Fatal Error Backtraces
- INI Diff Option
- Support for Closures in Constant Expressions
See the PHP 8.5 RFC page for a complete list.
The Pipe Operator
The Pipe Operator is an exciting prospect for PHP developers wanting to chain multiple callables together, passing a value through them from left to right in a native way:
// Using the pipe operator in PHP 8.5$result = "Hello World" |> htmlentities(...) |> str_split(...) |> fn($x) => array_map(strtoupper(...), $x) |> fn($x) => array_filter($x, fn($v) => $v != 'O');
Native array_first() and array_last() Functions
PHP 8.5 will include array_first() and array_last() functions. While on the surface, these functions might not seem like a huge deal (and the PHP community has userland implementations and polyfills), these functions are long overdue as native functions in the PHP language.
These functions complement the already provided array key methods merged in PHP 7.3:
In PHP 7.3, we got
array_key_first()andarray_key_last()to get the first and last keys from an array. What we don't have yet is a way to get the first and last values of an array. This is harder than you may think because:
- The array keys are not necessarily integers, not necessarily starting with 0, etc...
- Existing “tricks” like
reset()andend()are semantically the wrong approach because they modify the “internal iterator” of the array. Furthermore, it also does not work properly on all types of expressions (e.g. an array returned from a function / plain array can cause a notice due to the by-ref argument).- Using
$array[array_key_first($array)]is cumbersome
We have a more detailed post on array_first() and array_last() if you want to dive deeper, but here are some examples of the function signatures and how they work:
// Function signaturesfunction array_first(array $array): mixed {}function array_last(array $array): mixed {} // Examplesarray_first(["single element"]); // "single element"array_last(["single element"]); // "single element" array_first([]); // NULLarray_last([]); // NULL array_first([1 => 'a', 0 => 'b', 3 => 'c', 2 => 'd']); // 'a'array_last([1 => 'a', 0 => 'b', 3 => 'c', 2 => 'd']); // 'd' $str = "hello";array_first([&$str, false]); // "hello" (no ref)array_last([false, &$str]); // "hello" (no ref)
A New URI Extension
PHP 8.5 introduces a new URI extension, which is a standards-compliant parser "for both RFC 3986 and the WHATWG URL standard as an always-available part of its standard library within a new 'URI' extension." The RFC has plenty of examples, but here's one from the PHP foundation announcement post showcasing the RFC 3986 Uri class:
use Uri\Rfc3986\Uri; $url = new Uri('HTTPS://thephp.foundation:443/sp%6Fnsor/'); $defaultPortForScheme = match ($url->getScheme()) { 'http' => 80, 'https' => 443, 'ssh' => 22, default => null,}; // Remove default ports from URLs.if ($url->getPort() === $defaultPortForScheme) { $url = $url->withPort(null);} // Getters normalize the URL by default. The `Raw`// variants return the input unchanged. echo $url->toString(), PHP_EOL;// Prints: https://thephp.foundation/sponsor/echo $url->toRawString(), PHP_EOL;// Prints: HTTPS://thephp.foundation/sp%6Fnsor/
Retrieve the Currently Executing Closure
PHP 8.5 will support recursion in Closures by fetching the currently executing Closure (hat tip to Alexandre Daubois). As pointed out in the rfc:closure_self_reference RFC, the current workaround is binding a variable reference into a closure. PHP 8.5 provides the static Closure::getCurrent() to get the currently running closure:
$fibonacci = function (int $n) { if (0 === $n || 1 === $n) { return $n; } $fn = Closure::getCurrent(); return $fn($n - 1) + $fn($n - 2);}; echo $fibonacci(10) . "\n";
Support for Closures in Constant Expressions
PHP 8.5 introduces support for closures in constant expressions, making it possible to define a default attribute value as a Closure, among other use-cases:
function my_array_filter( array $array, Closure $callback = static function ($item) { return !empty($item); },) { $result = []; foreach ($array as $item) { if ($callback($item)) { $result[] = $item; } } return $result;} my_array_filter([ 0, 1, 2, '', 'foo', 'bar',]); // [1, 2, "foo", "bar"]
See our detailed post on this feature to learn more.
PHP Fatal Error Backtraces
A new fatal_error_backtraces setting can control whether a backtrace is shown for fatal errors. The fatal_error_backtraces setting will default to 1 in PHP 8.5—you don't have to configure anything to get these backtraces (though you can disable them if you want). Fatal errors without backtraces in today's stable PHP versions (i.e., PHP 8.4) might include parse errors (syntax errors), duplicate functions or classes, infinite loops with a max execution time, etc.
Fatal error: Cannot redeclare class B (previously declared in /srv/app/index.php:11) in /srv/app/b.php on line 3Stack trace:#0 /srv/app/index.php(6): require()#1 /srv/app/index.php(21): A->loadClassB()#2 {main}
INI Diff Options
PHP 8.5 introduces a INI diff option for the php --ini flag that makes it easy to identify changed INI values in your configuration. The --ini flag is helpful to show the loaded php.ini configuration file, as well as additional .ini files parsed:
$ php --ini=diffNon-default INI settings:allow_url_include: "0" -> ""auto_append_file: (none) -> ""auto_prepend_file: (none) -> ""display_errors: "1" -> ""display_startup_errors: "1" -> ""enable_dl: "1" -> ""error_reporting: (none) -> "22527"...
Learn More
To get up to speed on these new features, check out the PHP 8.5 Release Announcement page for examples before/after PHP 8.5. Be sure to check out the deprecations and backward compatibility breaks.
The following list of additional resources has everything you need to learn more about this release:
- The UPGRADING document includes backward-incompatible changes, new features, and everything else you'll need to familiarize yourself with changes in PHP 8.5
- The NEWS document has detailed notes about each release
- The PHP 8.5 preparation tasks page has the release timeline of the upcoming releases
- You can download PHP 8.5 source from the downloads page