PHP 8.4 released on November 21, 2024, with this release there will be new features, improvements, deprecation’s and more.
Let’s check the new features added on PHP 8.4
New Features
- New array_find functions
PHP 8.4 comes with new array functions array_find() and their counterparts array_find_key(), array_any(), array_all(). array_find() retrieves the first matching element that fulfills the callback condition. You can think of it like Javascript Array.find method.
$posts = [ [ 'id' => 1, 'title' => 'Post 1' ], [ 'id' => 2, 'title' => 'Post 2' ], [ 'id' => 3, 'title' => 'Post 3' ] ]; $findPost = array_find($posts, fn($post) => $post['id'] === 2); echo $findPost['title']; // Post 2
All array_find() functions accepts the target array and a callback. If the callback returns “true” at any point, it will stop searching and return immediately.
array_find_key() returns the key of the first element for which the $callback
returns true. If no matching element is found the function returns NULL.
$findIndex = array_find_key($posts, fn($post) => $post['id'] === 3); echo $findIndex; // 2
array_any()
and array_all()
return a boolean instead of a value.
array_any()
return true
if at least one element within the array matches a callback’s condition,
$numbers = [1, 3, 10, 14, 20]; $isThereNumberGreaterTen = array_any($numbers, fn($num) => $num > 10); var_dump($isThereNumberGreaterTen); // bool(true)
while the array_all()
function return true if all elements matches a callback’s condition.
$isAllNumbersGreaterTen = array_all($numbers, fn($num) => $num > 10); var_dump($isAllNumbersGreaterTen); // bool(false)
- New Multibyte String Functions
In PHP 8.4 new multibyte string functions added for functions like trim()
, ltrim()
and rtrim()
, etc. Now there are are mb_trim()
, mb_ltrim()
, mb_rtrim()
, mb_ucfirst()
, mb_lcfirst()
.
- new without parenthesis
PHP 8.4 provides a short syntax for accessing methods and properties when using the new keyword. Prior to PHP 8.4 in order to invoke a class method directly, you have to wrap the new keyword within parenthesis:
PHP < 8.4
class Post { private string $title = ""; public function setTitle(string $title) { $this->title = $title; return $this; } public function getTitle() { return $this->title; } } $post = (new Post())->setTitle("Post title"); // Parenthesis required
With PHP 8.4
$post = new Post()->setTitle("Post title");
With this feature method chaining becomes short:
$post = new Post()->setTitle("Post title") ->getTitle(); echo $post
You can also access properties and constants the same way:
class Foobar { const SUBJECT = "subject"; public $title = "sample title"; public static $admin = "admin"; } new Foobar()::SUBJECT; // subject new Foobar()->title; // sample title new Foobar()::$admin; // admin
- Property Hooks
Another nice feature comes with PHP 8.4 is the Property Hooks inspired from C# or Kotlin. Previously when we need to set and retrieve properties we tend to declare a custom getter and setter methods for that property, or using the PHP magic methods __set() and __get().
Consider the previous Post class:
class Post { private string $title = ""; public function setTitle(string $title) { $this->title = $title; return $this; } public function getTitle() { return $this->title; } }
Now with PHP 8.4 we can utilize the Property Hooks syntax and redefine the getters and setters for $title like so:
class Post { public string $title { get => $this->title; set { $this->title = $value; } } }
Then we can set and get the property using class instance:
$post = new Post(); $post->title = "sample post"; echo $post->title; // sample post
As you see the terminology for a property hook:
<visibility modifier> <type> <$property> { get {} set() {} }
Most notably you don’t have to define get() and set() hooks altogether, you can define any of them:
class Post { public string $title { set { $this->title = $value; } } }
- Asymmetric Visibility
Prior to PHP 8.4 when declaring class properties with visibility, this visibility applies on both read and write operations:
class Post { public string $title = ""; public function __construct(string $title) { $this->title = $title; } }
Because the $title property is made public, user can set and read it from outside the class:
$post = new Post("post title"); $post->title = "updated post title"; echo $post->title;
In this code the user can set the property directly using $post->title. What about if we want to prevent writing to the property directly from outside, but keeping access it. This is where the Asymmetric visibility comes into place.
The Asymmetric Visibility feature in PHP 8.4 allows us to define a different visibility modifier on read and write contexts for class properties.
Let’s redeclare property $title by allowing public read and preventing writing from outside:
class Post { public private(set) string $title = ""; public function __construct(string $title = "") { $this->title = "title"; } }
Now the property can be set only when initializing the class. With this code if you run the above script you will get an error like this:
Fatal error: Uncaught Error: Cannot modify private(set) property Post::$title from global scope
This is valid:
$post = new Post("post title"); echo $post->title;
From this code the Asymmetric visibility can be defined like so:
<read visibility> <set visibility>(set) <type> $property
Asymmetric visibility also works with Property Hooks to disallows setting property from outside:
class Post { public private(set) string $title { set(string $value) { $this->title = $value; } } public function __construct(string $title) { $this->title = $title; } }
This is valid:
$post = new Post("post title"); echo $post->title;
This is invalid:
$post = new Post("post title"); $post->title = "updated title"; // invalid echo $post->title;
- JIT Changes
Just-in-Time Compilation (JIT) comes with PHP 8.0 which is disabled by default. To enable it set the INI variable opcache.jit_buffer_size
.
< PHP 8.4 the configuration:
opcache.jit=tracing opcache.jit_buffer_size=0
Now with PHP 8.4 the configuration becomes:
opcache.jit=disable opcache.jit_buffer_size=64M
- New HTML5 Support
A new class added in PHP 8.4 in related to DOM manipulation which is the HTMLDocument available in the \Dom namespace:
$doc = \Dom\HTMLDocument::createFromString($contents); $doc = HTMLDocument::createEmpty(); $doc = HTMLDocument::createFromFile($path);
- New
request_parse_body()
Function
In PHP apps typically we manipulate post data using $_POST
and $_FILES
superglobals. However there are a limitation for other HTTP methods like PUT
and PATCH
especially for REST Webservices which depends on other HTTP methods like PUT and PATCH or DELETE. In PHP 8.4 new function added for this purpose request_parse_body():
[$_POST, $_FILES] = request_parse_body();
The function return an array of two items, where the first item contains the $_POST
data and the second item contains the $_FILES
data.
- Dealing with
exit()
anddie()
as Functions
In PHP exit()
and die()
are language constructs not functions for example it doesn’t support named arguments and couldn’t be passed as callable and it can be written as exit;
or exit(0)
. With PHP 8.4 this behavior change and exit()
and die()
will be treated as functions.
Deprecations
- Implicit Nullable Types not allowed
In PHP 8.4 you have to explicitly declare a value that have a null value using the nullable type like so:
function getItems(string $a, ?string $b = null) {}
- Deprecation of GET/POST sessions
Sessions used to track user state. In PHP we can also use GET/POST to store user state via disabling the setting session.use_only_cookies
and session.use_trans_sid
INI variables. By default, “session.use_only_cookies
” is enabled, and “session.use_trans_sid
” is disabled. Starting in PHP 8.4, if either value is toggled differently, PHP will raise a deprecation warning
Additional New PHP 8.4 Features
- Driver-specific PDO subclasses to allow access to driver-specific features.
- round() function new rounding modes.
- Lazy Objects Support
- A new attribute, #[Deprecated], for marking deprecated functionality.