New Features Coming in PHP 7.4

Ruden
Valeriy Rudenko

PHP 7.4, the next PHP 7 minor release, is expected to be released to the General Availability on November 28th, 2019. So it’s time for us to dive into some of the most exciting additions and new features that will make PHP faster and more reliable.

Actually, even if PHP 7.4 significantly boosts performance and improves code readability, PHP 8 will be the real milestone for PHP performance, as the proposal for JIT inclusion has already been approved.

Spread operator updates

PHP has had support for the spread operator for a while. It's functionality has been limited to unpacking functional arguments. For example. You've been able to do the following since PHP 5.6.

function spreadArgs(...$args) {
    print_r($args);
}

spreadArgs(...[1, 2, 3, 4]);
spreadArgs(1, 2, 3, 4);

/*
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
)
*/

This new RFC will add spread functionality to the array expression. That means unpacking arrays inline like so

$vine_veges = ['cucumber', 'pumpkin'];
$ground_veges = ['carrots', 'potatos'];

print_r(['eggplant', ...$vine_veges, ...$ground_veges]);

/*
Array
(
    [0] => eggplant
    [1] => cucumber
    [2] => pumpkin
    [3] => carrots
    [4] => potatos
)
*/

This unpacking works with both array() and [] syntax. You can also unpack arrays returned directly from functions.

function get_colours($additional_colours = []) {
  return ['red', 'green', 'blue', ...$additional_colours];
}

print_r(['yellow', ...get_colours(['purple', 'green']), 'black']);

/*
Array
(
    [0] => yellow
    [1] => red
    [2] => green
    [3] => blue
    [4] => purple
    [5] => green
    [6] => black
)
*/

The unpacking syntax doesn't work with associative arrays. So it's not as flexible as it's Javascript counterpart.

Arrow functions

While PHP has supported closures for some time, they tend to be quite verbose. This RFC adds arrow functions and short function syntax to PHP. Take this code example from the RFC.

function array_values_from_keys($arr, $keys) {
    return array_map(function ($x) use ($arr) { return $arr[$x]; }, $keys);
}

With the new syntax this can be shortened to be

function array_values_from_keys($arr, $keys) {
    return array_map(fn($x) => $arr[$x], $keys);
}

Few things to notice there, there's a new shortened function fn operator, also the scoping has been simplified so that the variable $arr is in scope to the function without the need for the use statement.

I'm genuinely excited about this as I find this code.

/* inline */
array_filter(range(0, 1024), fn($b) => $b % 64 === 0);

/* variable function */
$factor = fn($number) => $number % 64 === 0;
array_filter(range(0, 1024), $factor);
A lot cleaner than these variants.

/* inline */
array_filter(range(0, 1024), function($b) {
    return $b % 64 === 0;
});

/* variable function */
$factor = function($number) {
    return $number % 64 === 0;
}
array_filter(range(0, 1024), $factor);

Typed properties

PHP has supported types in some form or another for quite a while. Argument types have been a staple since version 5 and since version 7, PHP also supports return types. It'spretty standard to see class definitions like this.

class MyClass {

/* int */
protected $count = null;

/* MyClass */
protected $sibling;

/**
* @param $sibling MyClass
* @return array
*/
public function addSibling(MyClass $sibling): array
{
    $this->sibling = $sibling;

    return [
    'count' => $this->count++,
    'current_sibling' => $this->sibling
    ];
    }
}

With typed properties we'll also be able to define the types of the class properties.

class MyClass {

    protected ?int $count = null;
  
    protected MyClass $sibling;

/* ... */
}

This improves code readability and will also help debugging and IDE support.

Currently the supported types are.

  • int
  • bool
  • float
  • string
  • array
  • object
  • iterable
  • self
  • parent
  • any class or interface name
  • ?type where type may be any of the above.

The preceding ? tells the run-time interpreter that the property can be null.

There's a lot more to typed properties than I've covered here so go and have a read over at the RFC page.

Null Coalescing Assignment

PHP 7 introduced the Null Coalescing Operator as a shorthand for common usage of the ternary operator. As per the documentation:

The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.

// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

// Coalescing can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';

The Null Coalescing Assignment Operator takes this a step further. Consider the case of defining defaults.

/* Standard Conditional */
function setName($name = null) {
if (!$name) {
$name = 'default';
}
/* ... */
}

/* Ternary (Elvis Operator) */
function setName($name = null) {
    $name = $name ?: 'default';
    /* ... */
}

/* Null Coalescing */
function setName($name = null) {
    $name = $name ?? 'default';
    /* ... */
}

/* Null Coalescing Assignment */
function setName($name = null) {
    $name ??= 'default';
    /* ... */
}

As you can see the syntax is a lot cleaner. Another benefit is that it's safe to undefined values.

$details = [[], ['category' => 'Red']];

/* Ternary/Elvis */
$details[0]['category'] = $details[0]['category'] ?: 'Blue';

// PHP Notice:  Undefined index: category in php shell code on line 1

/* Null Coalescing */
$details[0]['category'] = $details[0]['category'] ?? 'Blue';

// 'Blue'

/* Null Coalescing Assignment */
$details[0]['category'] ??= 'Blue';

// 'Blue'

One more

I'm not a massive fan of all the new features. Take, for example the Numeric Literal Separator.

This feature enables the ability to make numeric literals easier to read for developers. By adding an underscore separator to Numerical Literals. The underscore is removed during runtime so is ignored by the interpreter. It's completely optional.

// a billion!
(1000000000 === 1_000_000_000) // true

// scale is hundreds of millions
(107925284.88 === 107_925_284.88) // true

// $135, stored as cents
(13500 === 135_00) // true

While I appreciate that it makes the intention of the original developer easier to decode, this one seems a tad strange to me.

Migrate To PHP7

Migrate To PHP7

Migrate To PHP7

What if you could double the page speed of your osCommerce site in just 20 minutes? Sounds amazing right? All you have to do is upgrade to the latest version of PHP. The support for PHP 5.6 ends by the end of 2018. If it’s not possible for you to migrate to osCommerce Community Edition now, perhaps it’s wise to consider changing the PHP version to 7.0.

Migrate to PHP7 services include:
$49

(0)