PHP 8.4 What's updated and new

Mar 28, 2025
An illustration representing the latest PHP release with the number 8.4 in glowing gold

-sidebar-toc>        -language-notice>

With the addition of new features, improvements, and deprecations, we anticipate at this time of the year that 2024 will see changes to PHP's release cycle, including the closing of security releases that are supported by all versions currently which were synced until the close of the year, instead of the GA birthday.

What's more, that support was extended by one year. That means that you'll be using PHP 8.4 safely through 2028 (with two years of security and bug fixes and two years of only security fixes).

If you're capable of spending more time using PHP 8.4 however, you'll need to find out what's new in this release today. So, let's jump in.

Improved features and enhancements are available in PHP 8.4

Hooks for property

To illustrate how property hooks could replace the class shown below includes the properties the $size and flavor. The properties are protected by private visibility to protect the properties from access by anyone outside the resulting object. The reason for this is that these methods, which are accessible to the public, mediate access to the properties:

class Coffeeend of class. Make the coffee you want to drink. Coffee('Small' "Pumpkin Spice'); print getSize of $coffee() . ' ' . $coffee->getFlavor(); // Prints "Small Pumpkin Spice" // Change order $coffee->setSize('Grande'); $coffee->setFlavor('Mocha'); print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Grande Mocha"

Maybe your class has many property types, and instead of writing a variety of methods for getting and setting them, you use PHP's _get and set magical methods. Perhaps you can even figure things out in a somewhat messy switch declaration like the one below.

// __set magic method example public function __set(string $key, $value): void switch ($key)  case 'size': $this->size = $value; break; case 'flavor': $this->flavor = $value; break; default: throw new InvalidArgumentException('Invalid input');  } // Later, we can change the coffee order like this: $coffee->size = 'Grande'; $coffee->flavor = 'Mocha';

Whatever method you decide to use, the more properties you have in your class, how far the code that you employ to manipulate them will be in relation to their definitions at the uppermost part of your class file. What's more, some methods that implement the _get and set magic methods can unexpectedly provide access to protected or private properties within your object which you hadn't intended to expose.

The brand new property hooks the ability to setter and getter functions along with the property properties. In the property hooks example below, you'll notice that the properties $size and the $flavor properties in the Coffee class have been made public. We've also included some fundamental validation for set hooks. sets of hooks to distinguish these from direct assignments.

// Property definitions at the top of our Coffee class class Coffee  public string $flavor  set(string $value)  if (strlen($value) > 16) throw new InvalidArgumentException('Input is too long'); $this->flavor = $value;   public string $size  set(string $value)  if (! in_array($value, array('Small', 'Grande'))) throw new InvalidArgumentException('Not a valid size'); $this->size = $value;   // Rest of the Coffee class  // Define a coffee $coffee = new Coffee(); $coffee->size = 'Grande'; $coffee->flavor = 'Pumpkin spice';

Similar to what you observe in the following an get hook is able to pack functions into what appears to be an ordinary reference to an object property.

// Simplified Coffee class class Coffee// Make a flavor $coffee = new (); $coffee->flavor = new() the $coffee->flavor variable is "Pumpkin". stores the value "Pumpkin" print the $coffee->flavor of coffee // Prints "Pumpkin Spice"

Contrary to PHP magic techniques, property hooks can be used in interfaces and abstract classes. An interface example:

interface Coffee: get; set;

Asymmetric visibility

Setter and getter that are publicly visible methods we looked at earlier are the standard method of accessing private and protected properties in their respective classes.

An interesting feature in the PHP 8.4 is the possibility of properties to enjoy distinct levels of visibility, based on the context in which it is accessed. So, a property might be public when being read however private or secured by setting.

Check this out:

class: Coffee  public private(set) string $flavor = 'Pumpkin Spice';  $coffee = coffee with a new flavor() printing $coffee->flavor. Prints "Pumpkin Spice" The flavor in the $coffee->flavor is 'Mocha' The error message is (visibility)

In the above example, the class's flavor property is only available in a setting context. It's pretty simple already and asymmetric visibility offers an escape route:

class Coffee  // public is assumed when the context is not setting private(set) string $flavor = 'Pumpkin Spice'; 

Property hooks and asymmetric visibility to create a tremendous versatility when working with the object properties of various visibilities.

Chaining is a brand new concept without parentheses

When it comes to shorthands, there are the new chains and methods of chaining required placing the invocation in parentheses, like this:

$coffee = (new Coffee())->getFlavor()->getSize();

PHP 8.4 permits this:

$coffee = new Coffee()->getFlavor()->getSize();

This may appear to be a small change, but removing just two parentheses makes the code easy to understand and troubleshoot.

New functions for finding the array of items

In the "You think we can't have that?" department, PHP 8.4 introduces the function array_find(), which will search the array for members matching conditions expressed in a callback. The function returns the value of the first element matching the callback's test.

The new release includes three other related functions:

  • array_find_key(): Like array_find(), but the return value is the matching element's key instead of the actual value of the elements itself.
  • array_all(): Returns true if each element of the array that is being examined is in line with the test of the callback.
  • array_any(): Returns the value if at least one of the elements within the array matches the criteria of the callback.

It is important to note that the two functions will return the boolean type of indicators, not array keys or content.

Here are some quick examples:

$array = [ 'a' => 'Mocha', 'b' => 'Caramel', 'c' => 'Maple', 'd' => 'Pumpkin' ]; // Find the first flavor name that is 5 characters long var_dump(array_find($array, function (string $value)  return strlen($value) == 5; )); // Returns "Mocha," even though "Maple" is the same length // Find the array key for the first flavor with a name longer than 5 characters. var_dump(array_find_key($array, function (string $value)  return strlen($value) > 5; )); // Returns "b" // Check to see if any flavor name is less than 5 characters long var_dump(array_any($array, function (string $value)  return strlen($value) 

HTML5 parsing

HTM5 is the standard for the structure of contemporary web pages. PHP's Document Object Model (DOM) technology for parsing had stopped at HTML 4.01.

Instead of re-inventing the DOMDocument class that works with the older HTML standard, PHP 8.4 comes with an entirely brand new DomHTMLDocument class that's HTM5-ready.

It is possible to import the content of an HTML5 webpage in the following manner:

$document = DomHTMLDocument::createFromString($html)

In addition to the createFromString($html) constructor above, the class also supports createFromFile($path) and createEmpty()

The new parser recognizes semantic HTML5 tags like the main, article and section which are familiar to most of us.

Multibyte trim functions

Another feature of PHP 8.4 which appears to has been a while coming is multibyte support in trim functions.

  •      mb_trim()    
  •      mb_ltrim()    
  •      mb_rtrim()    

As with the long-running PHP trim() function, the mb_trim function takes out white space and some special characters, like line feeds, from both ends of a string that may include multibyte characters. The other functions trim either the left or right ends of the string.

Precautions in PHP 8.4

Each release of PHP includes a plethora of new features and functions (some rather obscure) that have been flagged as potential removals of the PHP platform. The most prominent change in PHP 8.4 is non-cookie session tracking.

Deprecation of GET/POST session

With PHP 8.4, either of these settings will trigger a warning about deprecation that might appear in your website logs. Once PHP 9 is released, the settings won't be in use.

Other changes (and removals) in PHP 8.4

Here is a complete list of functionality targeted for deprecation by the developers responsible for PHP 8.4. (Some contain links to further details on the capabilities.,

  • Formally deprecate soft-deprecated properties of DOMDocument and DOMEntity properties.
  • Removed DOMImplementation::getFeature($feature, $version).
  • Deprecate DOM_PHP_ERR constant.
  • Deprecate The "S" tag in our unserialize().
  • Deprecate session.sid_length and session.sid_bits_per_character.
  • Deprecate SplFixedArray::__wakeup().
  • Remove the xml_set_object() and the xml_set_*_handler() with string method names.
  • It is not recommended to pass null or false to the dba_key_split().
  • Deprecate passing incorrect data types in the ext/hash function for various options.
  • Deprecate constants SUNFUNCS_RET_STRING, SUNFUNCS_RET_DOUBLE, SUNFUNCS_RET_TIMESTAMP.
  • Refrain from using the CSV's proprietary CSV escaping mechanism.
  • Deprecate E_STRICT constant.
  • Deprecate strtok().
  • Deprecate returning non-string values from an output handler for users.
  • It is not recommended to produce output within a user-specific output handler.
  • Remove file_put_contents() with the $data as an array.
  • Remove mysqli_ping() and mysqli::ping()
  • Deprecate mysqli_refresh().
  • Deprecate mysqli_kill().
  • Deprecate the second parameter to mysqli_store_result().
  • Deprecate lcg_value().
  • Deprecate the term uniqid().
  • Remove md5() and sha1() and md5_file() as well as sha1_file().
  • It is not recommended to pass E_USER_ERROR to cause an error().
  • Deprecate using a single underscore ("_") for a class name.
  • Deprecate SOAP_FUNCTIONS_ALL constant and passing it to SoapServer::addFunction().

Summary

    Which PHP 8.4 features are your top picks? Tell us your experiences with the PHP 8.4 community in the comments!

Steve Bonisteel

Steve Bonisteel is a Technical Editor at who began his writing career as a print journalist, chasing fire trucks and ambulances. He's been writing about internet-related technologies since the mid 1990s.