What's new in PHP 8.4

Published in Originals on Nov 13, 2024

It's that time again, a new version of PHP. Version 8.4 already.
This version is packed with changes and new features, changes and deprecations.
Here is a summary of the features I can't wait to play around with.

The release date for PHP 8.4 is officially 2024-11-21. So that's next week.

Let's start of with deprecations, there is only one that I want to highlight.

Implicitly nullable parameter declarations

We had this strange thing around that made a variable nullable. I was never a fan of using this though.

function performAction(array $data = null) {}

// Implicitly marking parameter $data as nullable is deprecated, the explicit nullable type must be used instead

If we now want to make the variable $data explicitly nullable we can now add a ? before it.

function performAction(?array $data = null) {}

New Array functions

There are 4 new array functions available for us, which we can use to search and inspect array elements ith a callback function: array_find, array_find_key, array_all, and array_any.

array_find

This function will return the value of the first element for which the callback returns true.

function is_even(int $value): bool {
    return $value % 2 === 0;
}

array_find([1, 2, 3, 4, 5], 'is_even');
// 2

array_find_key

This function will return the key of the first element for which the callback returns true.

function is_even(int $value): bool {
    return $value % 2 === 0;
}

array_find_key(['foo' => 1, 'bar' => 2, 'baz' => 3], 'is_even');
// "bar"

array_all

This function will return true if the callback returns true for all elements of the array.

array_all(
    ['foo@example.com', 'bar@example.com', 'baz@example.com'],
    fn($value) => filter_var($value, FILTER_VALIDATE_EMAIL),
);
// true

array_all(
    ['foo@example.com', 'bar@example.com', 'baz'],
    fn($value) => filter_var($value, FILTER_VALIDATE_EMAIL),
);
// false

array_any

This function will return true if the callback returns true for any element of the array.

array_any(
    ['foo@example.com', 'https://php.watch', 'foobar'],
    fn($value) => filter_var($value, FILTER_VALIDATE_URL),
);
// true

New mb_ucfirst and mb_lcfirst functions

PHP had ucfirst and lcfirst for ages. Until now mbstring didn't support a multi-byte safe version or alternative for the ucfirst and lcfirst functions.
But now the wait is over, now we can use mb_ucfirst and mb_lcfirst. In addition, like the other mb_ functions it also accepts an optional encoding parameter.

mb_ucfirst('Bert'); // Best 
mb_ucfirst('BERT'); // BERT
mb_ucfirst('bErt'); // BErt
mb_ucfirst('bert'); // BErt

mb_lcfirst('Bert'); // bert
mb_lcfirst('BERT'); // bERT
mb_lcfirst('bErt'); // bErt
mb_lcfirst('bert'); // bert

New rounding modes

The round() function will round a given float to the nearest integer or decimal (based on a precision). with PHP 8.4 we'll be able to use 4 new rounding methods.

PHP_ROUND_CEILING

This method will round to the nearest integer bigger than the number.
For example 1.1 and 1.5 to 2 and -1.1 and -1.5 to -1

PHP_ROUND_FLOOR

This method will round to the nearest integer lower than the number.
For example 1.1 and 1.9 to 1 and -1.1 and -1.9 to -2

PHP_ROUND_TOWARD_ZERO

This method will round to the nearest integer in the direction of 0.
For example 1.1 and 1.9 to 1 and -1.1 and -1.9 to -1

PHP_ROUND_AWAY_FROM_ZERO

This method will round to the nearest integer in the direction away from 0.
For example 1.1 and 1.9 to 2 and -1.1 and -1.9 to -2

New without parentheses

We'll be able to create new object and call methods directly on them without wrapping them into parentheses.

// Prior to PHP 8.4
$result = (new SomeNewClass($param))->getSomething();

// In PHP 8.4
$result = new SomeNewClass($param)->getSomething();

Default Bcrypt cost changed from 10 to 12

The default cost used in the built-in password hashing changed from 10 to 12 for both PASSWORD_BCRYPT and PASSWORD_DEFAULT.

If needed we can still encrypt with a lower cost.

password_hash('verySafePassword', PASSWORD_BCRYPT, ['cost' => 10]);

Lazy Objects

We'll now have native support for lazy objects, a common pattern used by frameworks to build proxy objects.

$initializer = static function (MyClass $proxy): MyClass {
    return new MyClass(123);
};
 
$reflector = new ReflectionClass(MyClass::class);

$object = $reflector->newLazyProxy($initializer);

In closing

A bunch of new features, changes and deprecations. Which I think will make our work easier / faster in the long run.

Happy coding!



#php