Coming in WordPress 5.3: What is the PHP Spread Operator?

On October 9, Juliette Reinders Folmer announced on the core WordPress blog that WordPress 5.3 will use the spread operator. The spread operator was one of the new features made available in PHP 5.6, a version released in 2014.

WordPress abandoned PHP 5.2 – 5.5 with the release of WordPress 5.2. This means the core team can start taking advantage of relatively new features, or at least 5-year-old features. For plugin and theme developers who maintain the same minimum version support as WordPress, they can also start exploring this feature.

PHP 5.6 introduced two new methods of using the spread operator:

A Parameter in variadic functions.

Function argument unpacking of arrays and traversable objects.

This feature shouldn’t be confused with unpacking inside of arrays, which is only available in PHP 7.4.

The change in WordPress 5.3 is not expected to affect themes and plugins except in the rare case that a developer is overloading the wpdb::prepare() method. Developers should read the announcement post to dive into what code has changed in core WordPress.

Developers should check their plugins and themes with debugging enabled in a test environment to check for any notices. There may be cases where the function signature doesn’t match.

The spread operator is a tool, and like any tool, it should be used when it makes sense. Because it is a language construct, it does offer speed improvements over traditional methods of using a PHP function.

The remainder of this post will dive into the using the spread operator to help teach WordPress developers how it works.

Creating a Variadic Function with the Spread Operator

Variadic functions are PHP functions that accept a variable number of arguments passed in. They have existed for years. However, they can be confusing without solid inline documentation from the developer who wrote the code.

In the past, developers would need to use the func_get_args(), func_get_arg(), or func_num_args() functions to work with variadic functions. In PHP 5.6, developers can use a parameter such as ...$var_name to represent a variable number of parameters.

Take a look at the following multiplication function. It will accept one, two, three, or even more numbers and multiply each.

function tavern_multiply( ...$numbers ) {

$total = 1;

foreach ( $numbers as $number ) {
$total = $total * intval( $number );
}

return $total;
}

If we use that function as shown below, it will display 1024:

echo tavern_multiply( 2, 4, 8, 16 );

This is simple to do with the spread operator.

Unpacking Arrays as Function Arguments

PHP 5.6 allows developers to unpack arrays and traversable objects as function arguments. To explain how this works, look at the following multiplication function for multiplying three numbers together.

function tavern_multiply_three( $x, $y, $z ) {
return $x * $y * $z;
}

Generally, you would need to manually pass the $x, $y, and $z parameters directly. However, there are cases in real-world projects where the data (numbers in this case) would already exist within an array such as:

$numbers = [ 3, 6, 9 ];

Prior to PHP 5.6, you would need to split that array and pass each value to the function as shown in the following snippet.

echo tavern_multiply_three( $numbers[0], $numbers[1], $numbers[2] );

With PHP 5.6, you can simply pass in ...$numbers like so:

echo tavern_multiply_three( ...$numbers );

Both methods work and will output 162. However, the second method is easier to read and is less prone to typos because it uses fewer characters.

Comparing Code Changes in WordPress

For a more practical example, let’s compare a real-world code change in WordPress and how using the spread operator improves the code over other methods. We can do this by looking at the core current_user_can() function.

First, see how the code is written in WordPress 5.2 and earlier.

function current_user_can( $capability ) {
$current_user = wp_get_current_user();

if ( empty( $current_user ) ) {
return false;
}

$args = array_slice( func_get_args(), 1 );
$args = array_merge( array( $capability ), $args );

return call_user_func_array( array( $current_user, 'has_cap' ), $args );
}

Without looking at the full function, most developers would assume that $capability is the only accepted parameter for this function. However, the function accepts a variable number of parameters. Previously, WordPress had to use func_get_args() to get all the parameters, slice the array, and merge everything back together.

It is inelegant coding, but it got the job done for old versions of PHP.

Now compare what the same function looks like in WordPress 5.3. First, you can see the ...$args parameter clearly in the function statement. You can also see there is no need for the clever coding to pass along a variable number of arguments.

function current_user_can( $capability, ...$args ) {
$current_user = wp_get_current_user();

if ( empty( $current_user ) ) {
return false;
}

return $current_user->has_cap( $capability, ...$args );
}

The change in WordPress 5.3 is a massive improvement in readability in comparison to earlier versions. It is nice to see these types of improvements to the core code.