What’s new in PHP 7.4
- Wiki: PHP 7.4
- github: PHP 7.4 changelog

[ ...$arr ] — array unpacking inside an array
Wiki: Spread operator for array
The ... operator is also called the “Splat Operator”, “Scatter operator” or “Spread operator”.
Unpacking works since PHP 5.6. And with the 7.4 release, we can use it inside arrays.
$parts = [ 'apple', 'pear' ]; $fruits = [ 'banana', 'orange', ...$parts, 'watermelon' ]; // [ 'banana', 'orange', 'apple', 'pear', 'watermelon' ];
Unpacking can be used multiple times, and unlike argument unpacking, ... can be used anywhere. You can add regular array elements before and after the ... operator.
Spread operator works for both the normal array syntax array() and the short [].
$arr1 = [ 1, 2, 3 ]; $arr2 = [ ...$arr1 ]; // [1, 2, 3] $arr3 = [ 0, ...$arr1 ]; // [0, 1, 2, 3] $arr4 = array( ...$arr1, ...$arr2, 111 ); // [1, 2, 3, 1, 2, 3, 111] $arr5 = [ ...$arr1, ...$arr1 ]; // [1, 2, 3, 1, 2, 3]
You can unpack a function call that returns an array.
function getArr(){
return [ 'a', 'b' ];
}
$arr6 = [ ...getArr(), 'c' ]; // ['a', 'b', 'c']
$arr7 = [ ...new ArrayIterator(['a', 'b', 'c']) ]; // ['a', 'b', 'c']
function arrGen(){
for( $i = 11; $i < 15; $i++ ){
yield $i;
}
}
$arr8 = [ ...arrGen() ]; // [11, 12, 13, 14]
IMPORTANT: String keys of an array are not supported!
To maintain compatibility with argument unpacking, string keys are not supported. If a string key is encountered, an error (recoverable error) will be thrown.
Unpacking by reference
It is not possible to unpack an array by reference.
$arr1 = [ 1, 2, 3] ; $arr2 = [ ...&$arr1 ]; // ERROR: invalid syntax
However, if the elements in the unpacked array are stored by reference, they will also be stored by reference in the new array.
$one = 1;
$arr1 = [ & $one, 2, 3 ];
$arr2 = [ 0, ...$arr1 ];
var_dump( $arr2 );
/*
array(4) {
[0]=> int(0)
[1]=> & int(1)
[2]=> int(2)
[3]=> int(3)
}
*/
Advantages over array_merge()
-
Spread operator should have better performance than array_merge() because it is a language construct, while array_merge() is a function call, and constant arrays can benefit from compile-time optimization.
-
array_merge() supports only arrays, while
...also supports Traversable objects.// when getting iterators array_merge( iterator_to_array($iter1), iterator_to_array($iter2) ) // when you may get either an iterator or an array array_merge( is_array($iter1) ? $iter1 : iterator_to_array($iter1), is_array($iter2) ? $iter2 : iterator_to_array($iter2) ) // all variants covered [ ...$iter1, ...$iter2 ]
public int $id — typing for class properties
Added support for types on class properties. For example:
class User {
public int $id;
public string $name;
}
Now $user->id can be only an integer, and $user->name can be assigned only strings.
More information via this RFC: https://wiki.php.net/rfc/typed_properties_v2
fn( $x ) => $x — arrow functions
Added support for arrow functions with implicit value-based scope binding. For example:
$factor = 10; $nums = array_map( fn( $num ) => $num * $factor, $nums );
As another example of the usefulness of this approach, consider how it was written before and how it can be written now:
function array_values_from_keys( $arr, $keys ) {
return array_map( function ($x) use ($arr) { return $arr[$x]; }, $keys );
}
The operation of passing the $arr parameter by closure is trivial, but it loses a bit in syntax. Arrow functions can shorten this function to the following:
function array_values_from_keys( $arr, $keys ) {
return array_map( fn( $x ) => $arr[$x], $keys );
}
Syntax
fn( array $x ) => $x; fn(): int => $x; fn( $x = 42 ) => $x; fn( & $x ) => $x; fn&( $x ) => $x; fn( $x, ...$rest ) => $rest;
More details in the RFC: https://wiki.php.net/rfc/arrow_functions_v2
covariance & contravariance
Added support for covariance of the return type and contravariance of the parameter type. Now the following code will work:
class A {}
class B extends A {}
class Producer {
public function method(): A {}
}
class ChildProducer extends Producer {
public function method(): B {}
}
Full variance support is available only when using autoloading. Within a single file, only non-cyclic type references are allowed, because all classes must be available before they are referenced.
A short note on Covariance and Contravariance.
More details on the RFC: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters
??= — coalesce assign operator
Added support for the coalesce assign operator ??=. For example:
$this->data['foo']['bar'] = $this->data['foo']['bar'] ?? 'value'; // Now you can write it as $this->data['foo']['bar'] ??= 'value';
Another example:
if ( ! isset( $array['key'] ) ) {
$array['key'] = computeDefault();
}
// the same, but short
$array['key'] ??= computeDefault();
More details on the RFC: https://wiki.php.net/rfc/null_coalesce_equal_operator
299_792 — underscore in numbers
Added support for underscore separators in numeric literals. For example:
6.674_083e-11; // float 299_792_458; // decimal 0xCAFE_F00D; // hexadecimal 0b0101_1111; // binary
RFC details: https://wiki.php.net/rfc/numeric_literal_separator
WeakReference — weak references
Added support for weak references (WeakReferences).
Weak references allow a programmer to keep a reference to an object without preventing its destruction; they are useful for implementing cache-like structures. Currently they are supported in PHP via an extension.
final class WeakReference {
public static function create(object $object) : WeakReference;
public function get() : ?object;
}
More details on the RFC: https://wiki.php.net/rfc/weakrefs
strip_tags( $str, ['a', 'p'] )
strip_tags() now also accepts an array of allowed tags:
// Instead of strip_tags( $str, '<a><p>' ); // you can now write strip_tags( $str, ['a', 'p'] );
__serialize() __unserialize() — magic methods
A new serialization mechanism for objects has been added, using two new magic methods:
// Returns an array containing all necessary object state. public function __serialize(): array; // Restores the object's state from the given data array. public function __unserialize( array $data ): void;
The new serialization mechanism replaces the Serializable interface, which will be deprecated in the future.
array_merge() — call with no arguments
array_merge() and array_merge_recursive() can now be called with no arguments, in which case they return an empty array. This is useful in combination with the spread operator, for example:
array_merge( ...$arrays )
Exceptions from __toString()
It is now allowed to throw exceptions from __toString(). Previously this caused a fatal error. Existing recoverable fatal errors during string conversion were converted to exceptions of type Error.
More details on the RFC: https://wiki.php.net/rfc/tostring_exceptions
—