What's New in PHP 7.4

In this post we’re covering several changes and features that should be added to the language with the final release of PHP 7.4, which is scheduled to be released in November of 2019 :

Arrow functions

Arrow functions, also called "short closures", are a way of writing shorter functions in PHP.

// A collection of Post objects
$posts = [/* … */];

$ids = array_map(fn($post) => $post->id, $posts);

// Previously, you'd had to write this:
$ids = array_map(function ($post) {
    return $post->id;
}, $posts);

Notes:-

  • They start with the fn keyword
  • They can only have one expression, which is the return statement
  • No return keyword allowed
  • Arguments and return types can be type hinted
  • don't require the use keyword to be able to access data from the outer scope.
  • you're not allowed to modify variables from the outer scope. Values are bound by value and not by reference.
  • One exception is of course the $this keyword, which acts exactly the same as normal closures:
$modifier = 5;
array_map(fn($x) => $x * $this->modifier, $numbers);

If you want to return a value by reference, the following syntax should be used:

fn&($x) => $x
  • The spread operator is also allowed
  • References are allowed, both for the arguments as the return values
$ids = array_map(fn(Post $post): int => $post->id, $posts);

Typed properties

Class variables can be type hinted, allow to specify the type of a variable that is expected to be passed to a function or a class method.

  • They are only available in classes and require an access modifier: public, protected or private; or var.
  • As of available types, almost all types can be used, except void and callable. Notes:-
  • The void type is not supported, because it is not useful and has unclear semantics.
  • The callable type is not supported, because its behavior is context dependent.

Here's a list of all available types:

  • bool, int, float, string, array, iterable, object, ? (nullable), self & parent, Classes & interfaces
class User {
	public int $id;
	public string $name;
}

They are also allowed with the var notation:

var bool $flag;

It’s possible to set default property values, which of course must match the declared property type, but only nullable properties can have a default null value:

public string $str = "foo";
public ?string $nullableStr = null;
public float $x, $y;

Coercion and strict types: PHP, being the dynamic language, will try to coerce or convert types whenever possible. Say you pass a string where you expect an integer, PHP will try and convert that string automatically:

class Bar
{
    public int $i;
}
$bar = new Bar;
$bar->i = '1'; // 1
  • you can disabled it by declaring strict types:
declare(strict_types=1);
$bar = new Bar;
$bar->i = '1'; // 1

/* 
Fatal error: Uncaught TypeError: 
Typed property Bar::$i must be int, string used
*/
  • It's hard to come up with any good use cases to overwrite the types of inherited properties. it's worth noting that it is possible to change the type of an inherited property, but only if the access modifier also changes from private to protected or public.
class Foo
{
    private int $prop;
}

class Bar extends Foo
{
    public string $prop;
}
  • changing a type from nullable to non-nullable or reverse, is not allowed in inheritance.
class Foo
{
    public int $a;
    public ?int $b;
}

class Bar extends Foo
{
    public ?int $a;
    public int $b;
}

// Fatal error: Type of Bar::$a must be int (as in class Foo)

Null coalescing assignment operator

a shorthand for null coalescing operations. the _?? operator is often used to check something's existence. coalesce equal or ??=operator is an assignment operator. If the left parameter is null, assigns the value of the right paramater to the left one. If the value is not null, nothing is made.

$data['date'] = $data['date'] ?? new DateTime();
// You can do this:
$data['date'] ??= new DateTime();

Array spread operator

Spread operator should have better performance than array_merge. That’s not only because the spread operator is a language structure while array_merge is a function, but also because compile time optimization can be performant for constant arrays.

  • A significant advantage of Spread operator is that it supports any traversable objects, while the array_merge function only supports arrays.
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); //[1, 2, 3, 1, 2, 3, 111]

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
var_dump($fruits);
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];

Numeric Literal Separator

Underscore separators can be used in all numeric literal notations supported by PHP:

var_dump(1_000_000); // int(1000000)
// The underscores are simply ignored by the engine.

Preloading

a feature that could improve the performance of your code significantly. This is preloading in a nutshell:

  • In order to preload files, you need to write a custom PHP script
  • This script is executed once on server startup
  • All preloaded files are available in memory for all requests
  • Changes made to the source file won't have any effect, until the server is restarted

For preloading to work, has to tell the server which files to load. This is done with a simple PHP script.

  • You provide a preload script and link to it in your php.ini file using opcache.preload
  • Every PHP file you want to be preloaded should be passed to opcache_compile_file(), from within the preload script
// you'd link to this script in php.ini:
opcache.preload=/path/to/project/preload.php

// here's a dummy implementation:
$files = /* An array of files you want to preload */;
foreach ($files as $file) {
    opcache_compile_file($file);
}

Custom object serialization

Two new magic methods have been added: __serialize and __unserialize.

// Returns array containing all the necessary state of the object.
public function __serialize(): array;
 
// Restores the object state from the given data array.
public function __unserialize(array $data): void;

Weak references

Weak references are references to objects, which don't prevent them from being destroyed.

$object = new stdClass;
$weakRef = WeakReference::create($object);

var_dump($weakRef->get());
unset($object);
var_dump($weakRef->get());

/*
The __first var_dump__ prints object(stdClass)#1 (0) {},
 while the __second var_dump__ prints NULL, as the referenced object has been destroyed.
*/

mb_str_split added

mb_str_split is a function to perform string splitting to an array of defined size chunks.

array mb_str_split (string $string [, integer $split_length = 1, string $encoding = mb_internal_encoding() ])
print_r(mb_str_split("huda", 2));
 
--EXPECT--
 
Array
(
    [0] => hu
    [1] => da
)

Password Hashing Registry

a new function password_algos has been added which returns a list of all registered password algorithms.

  print_r(password_algos());

Changes and deprecations

The following functions/functionalities will be deprecated with PHP 7.4.

Left-associative ternary operator deprecation

a deprecation warning for nested ternary statements. In PHP 8, this deprecation will be converted to a compile time error.

1 ? 2 : 3 ? 4 : 5;   // deprecated
(1 ? 2 : 3) ? 4 : 5; // ok
1 ? 2 : (3 ? 4 : 5); // ok

Concatenation precedence

a long standing issue that an (unparenthesized) expression with '+', '-' and '.' evaluates left-to-right.

echo "sum: " . $a + $b;
// In PHP 7.3 this code produces the following warning:
// Warning: A non-numeric value encountered

This because the concatenation is evaluated from left to right. It’s the same as writing the following code:

echo ("sum: " . $a) + $b;

// PHP 8 will make it so that it's interpreted like this:

echo "sum :" . ($a + $b);

Curly brackets for array and string access

It was possible to access arrays and string offsets using curly brackets: This has been deprecated.

$array{1};    // deprecated
$string{3};  // deprecated

strip_tags also accepts arrays

You used to only be able to strip multiple tags like so:

strip_tags($string, '<a><p>')

PHP 7.4 also allows the use of an array:

strip_tags($string, ['a', 'p'])
PHP#PHP

Comments (0)