PHP 8.4, set for release in November 2024, introduces a wide range of new features and improvements to enhance functionality, performance, and ease of use for developers. Key updates include new utility functions like array_find
and array_all
for better array handling, expanded HTTP/3 support in cURL, new functions for string manipulation (mb_ucfirst
, mb_lcfirst
), and enhanced support in DateTime
. Syntax updates include making exit
and die
true functions, and better handling for nullable parameters.
PHP 8.4 is one of the most anticipated updates for PHP developers this year, bringing a suite of new features and optimizations aimed at improving both performance and code readability. Here’s a deep dive into everything PHP 8.4 offers, complete with code examples to show how these updates can help you write better, more efficient PHP.
1. #[\Deprecated]
Attribute
The #[\Deprecated] attribute extends PHP's existing deprecation mechanism, allowing it to be applied to user-defined functions, methods, and class constants
Example:
// PHP < 8.4
class PhpVersion
{
/**
* @deprecated 8.3 use PhpVersion::getVersion() instead
*/
public function getPhpVersion(): string
{
return $this->getVersion();
}
public function getVersion(): string
{
return '8.3';
}
}
$phpVersion = new PhpVersion();
// No indication that the method is deprecated.
echo $phpVersion->getPhpVersion();
// PHP 8.4
class PhpVersion
{
#[\Deprecated(
message: "use PhpVersion::getVersion() instead",
since: "8.4",
)]
public function getPhpVersion(): string
{
return $this->getVersion();
}
public function getVersion(): string
{
return '8.4';
}
}
$phpVersion = new PhpVersion();
// Deprecated: Method PhpVersion::getPhpVersion() is deprecated since 8.4, use PhpVersion::getVersion() instead
echo $phpVersion->getPhpVersion();
2. New ext-dom features and HTML5 support
The updated DOM API introduces standards-compliant support for parsing HTML5 documents, resolves several longstanding compliance issues in DOM behavior, and includes new functions to simplify document handling.
This enhanced DOM API is accessible through the Dom
namespace. To utilize it, you can create documents using the Dom\HTMLDocument
and Dom\XMLDocument
classes.
Example:
// PHP < 8.4
$dom = new DOMDocument();
$dom->loadHTML(
<<<'HTML'
<main>
<article>PHP 8.4 is a feature-rich release!</article>
<article class="featured">PHP 8.4 adds new DOM classes that are spec-compliant, keeping the old ones for compatibility.</article>
</main>
HTML,
LIBXML_NOERROR,
);
$xpath = new DOMXPath($dom);
$node = $xpath->query(".//main/article[not(following-sibling::*)]")[0];
$classes = explode(" ", $node->className); // Simplified
var_dump(in_array("featured", $classes)); // bool(true)
// PHP 8.4
$dom = Dom\HTMLDocument::createFromString(
<<<HTML
<main>
<article>PHP 8.4 is a feature-rich release!</article>
<article class="featured">PHP 8.4 adds new DOM classes that are spec-compliant, keeping the old ones for compatibility.</article>
</main>
HTML,
LIBXML_NOERROR,
);
$node = $dom->querySelector('main > article:last-child');
var_dump($node->classList->contains("featured")); // bool(true)
3. Object API for BCMath
The new BcMath\Number
object introduces object-oriented functionality and support for standard mathematical operators when handling arbitrary precision numbers.
These objects are immutable and implement the Stringable
interface, allowing them to be seamlessly used in string contexts, such as echo $num
Example:
// PHP < 8.4
$num1 = '0.12345';
$num2 = 2;
$result = bcadd($num1, $num2, 5);
echo $result; // '2.12345'
var_dump(bccomp($num1, $num2) > 0); // false
// PHP 8.4
use BcMath\Number;
$num1 = new Number('0.12345');
$num2 = new Number('2');
$result = $num1 + $num2;
echo $result; // '2.12345'
var_dump($num1 > $num2); // false
4. PDO driver specific subclasses
The PDO class now includes new subclasses: Pdo\Dblib
, Pdo\Firebird
, Pdo\MySql
, Pdo\Odbc
, Pdo\Pgsql
, and Pdo\Sqlite
Example:
// PHP < 8.4
$connection = new PDO(
'sqlite:foo.db',
$username,
$password,
); // object(PDO)
$connection->sqliteCreateFunction(
'prepend_php',
static fn ($string) => "PHP {$string}",
);
$connection->query('SELECT prepend_php(version) FROM php');
// PHP 8.4
$connection = PDO::connect(
'sqlite:foo.db',
$username,
$password,
); // object(Pdo\Sqlite)
$connection->createFunction(
'prepend_php',
static fn ($string) => "PHP {$string}",
); // Does not exist on a mismatching driver.
$connection->query('SELECT prepend_php(version) FROM php');
5. DatePeriod Enhancements
Working with dates becomes easier with PHP 8.4's DatePeriod enhancements. It now supports more granular interval adjustments and better date range handling, which is particularly useful in data-driven applications that work with time periods.
Example:
$start = new DateTime('2023-01-01');
$end = new DateTime('2023-01-10');
$interval = new DateInterval('P2D');
$datePeriod = new DatePeriod($start, $interval, $end);
foreach ($datePeriod as $date) {
echo $date->format("Y-m-d") . "\n";
}
This update improves the functionality of DatePeriod
, making it easier to handle date-based data.
6. new MyClass()->method()
without parentheses
You can now access the properties and methods of a newly instantiated object directly, without the need to enclose the new
expression in parentheses
Example:
// PHP < 8.4
class PhpVersion
{
public function getVersion(): string
{
return 'PHP 8.3';
}
}
var_dump((new PhpVersion())->getVersion());
// PHP 8.4
class PhpVersion
{
public function getVersion(): string
{
return 'PHP 8.4';
}
}
var_dump(new PhpVersion()->getVersion());
7. Array Unpacking with String Keys
PHP 8.4 now supports array unpacking with associative arrays using string keys, a highly requested feature. This enhancement allows arrays with string keys to be merged with a simpler, more readable syntax.
Example:
$array1 = ['name' => 'John', 'age' => 30];
$array2 = ['location' => 'USA', 'age' => 32]; // Overwrite age
$mergedArray = [...$array1, ...$array2];
// Result: ['name' => 'John', 'age' => 32, 'location' => 'USA']
This addition simplifies the array merge syntax, reducing the need for cumbersome array functions.
8. Improved Named Arguments
PHP introduced named arguments in version 8.0, but it had limitations when working with certain dynamic scenarios. PHP 8.4 refines named arguments to support even more flexible naming conventions, improving code readability in complex functions with multiple parameters.
Example:
function createUser($username, $email, $role = 'user') {
// User creation logic
}
createUser(username: 'jdoe', email: 'jdoe@example.com', role: 'admin');
The refinements in PHP 8.4 allow for clearer, more manageable function calls.
9. Extended JIT Compiler Optimizations
The Just-In-Time (JIT) compiler introduced in PHP 8.0 has been further optimized in PHP 8.4, bringing increased performance, especially in CPU-intensive applications. With these enhancements, developers can expect faster execution times for complex operations, particularly beneficial in machine learning, data processing, and real-time applications.
Example:
// While no direct syntax change exists, the improvements here benefit
// all PHP scripts through enhanced runtime efficiency.
These JIT optimizations make PHP 8.4 a solid choice for CPU-bound tasks and large-scale applications.
10. Enhanced Error Messages and Debugging
In PHP 8.4, error messages are now more descriptive, providing better context when exceptions occur. This improvement aims to make debugging faster and reduce the amount of time spent identifying issues.
Example:
function divide($a, $b) {
if ($b === 0) {
throw new DivisionByZeroError("Cannot divide by zero.");
}
return $a / $b;
}
try {
divide(10, 0);
} catch (DivisionByZeroError $e) {
echo $e->getMessage(); // "Cannot divide by zero."
}
This provides a smoother debugging experience, especially in large applications where clear error messages are essential.
11. New Array Utility Functions
PHP 8.4 adds several array utility functions that simplify common operations:
-
array_find()
: This function helps locate the first item in an array that matches a given condition, making it easier to search within arrays.$result = array_find($array, fn($item) => $item > 10);
array_all()
: This checks if all elements in an array meet a specified condition, improving readability and reducing the need for custom loops.$allPositive = array_all($array, fn($num) => $num > 0);
These functions help reduce boilerplate code, making array manipulation cleaner and more concise.
12. String Manipulation Enhancements
Handling multibyte characters in PHP can be challenging, especially when working with non-Latin alphabets. PHP 8.4 introduces two new functions for multibyte string case conversion:
-
mb_ucfirst()
: Converts the first character of a multibyte string to uppercase.$string = mb_ucfirst("example");
mb_lcfirst()
: Converts the first character of a multibyte string to lowercase$string = mb_lcfirst("Example");
These additions streamline character case manipulation, particularly for applications needing multilingual support.
13. Enhanced HTTP/3 Support in cURL
PHP 8.4 expands support for HTTP/3 in the cURL extension, improving the performance and efficiency of applications that make heavy use of networking. HTTP/3, with its underlying QUIC protocol, is faster and more reliable for data transfer. This enhancement is valuable for applications requiring high-speed data requests, like APIs and real-time services.
14. Syntax Refinements: exit
and die
as Functions
In PHP 8.4, exit
and die
are redefined as true functions. This update removes inconsistencies in syntax, making exit
and die
behave like other standard functions. This change simplifies debugging and makes code formatting easier when using these exit points.
15. Property Hooks
In PHP 8.4, Property hooks are inspired by languages like Kotlin, C#, and Swift, and the syntax includes two syntax variants that resemble short and multi-line closures:
<?php
class User implements Named
{
private bool $isModified = false;
public function __construct(
private string $first,
private string $last
) {}
public string $fullName {
// Override the "read" action with arbitrary logic.
get => $this->first . " " . $this->last;
// Override the "write" action with arbitrary logic.
set {
[$this->first, $this->last] = explode(' ', $value, 2);
$this->isModified = true;
}
}
}
The syntax doesn't require that both hooks always be defined together; in fact, here's an example of only defining set
from the RFC:
class User
{
public string $name {
set {
if (strlen($value) === 0) {
throw new ValueError("Name must be non-empty");
}
$this->name = $value;
}
}
public function __construct(string $name) {
$this->name = $name;
}
}
16. Asymmetric Visibility
PHP 8.4 introduces new Asymmetric Property Visibility. This new capability allows properties to have separate visibility settings for reading and writing, offering greater flexibility and control.
<?php
class Book
{
public function __construct(
public private(set) string $title,
public protected(set) string $author,
protected private(set) int $pubYear,
) {}
}
class SpecialBook extends Book
{
public function update(string $author, int $year): void
{
$this->author = $author; // OK
$this->pubYear = $year; // Fatal Error
}
}
$b = new Book('How to PHP', 'Peter H. Peterson', 2024);
echo $b->title; // How to PHP
echo $b->author; // Peter H. Peterson
echo $b->pubYear; // Fatal Error
// PHP < 8.4
class PhpVersion
{
private string $version = '8.3';
public function getVersion(): string
{
return $this->version;
}
public function increment(): void
{
[$major, $minor] = explode('.', $this->version);
$minor++;
$this->version = "{$major}.{$minor}";
}
}
// PHP 8.4
class PhpVersion
{
public private(set) string $version = '8.4';
public function increment(): void
{
[$major, $minor] = explode('.', $this->version);
$minor++;
$this->version = "{$major}.{$minor}";
}
}
Allowing public access to a property while restricting public modifications (via set
) can be seen in the way $title
and $author
are publicly accessible. However, the ability to control how these properties are modified—using protected
or private
visibility for setters—demonstrates the granular control this feature provides. To use separate visibilities, class properties must have a defined type, and the setter's visibility must be the same as or more restrictive than the getter's visibility.
Conclusion
PHP 8.4 brings a wide range of updates that cater to developers looking for better performance, stricter typing, and a more powerful syntax. Whether you’re working with JSON, complex arrays, or heavily object-oriented projects, PHP 8.4 provides improvements that make your codebase cleaner, faster, and more maintainable.
If you’re using an earlier version of PHP 8.x, the transition to PHP 8.4 should be relatively smooth and will bring plenty of benefits, especially in larger applications where these optimizations have the most impact. Embrace the new features of PHP 8.4 to modernize your code, and enjoy the enhanced performance and developer-friendly updates that this release has to offer.