What’s New in PHP 7.3 (RC Now Available at Kinsta)

By Carlo Daniele Updated on October 25, 2018
700
Shares

PHP 7.3 is knocking on our door and with it comes new useful features, functionalities, deprecations, and a good number of bug fixes. This release is all about web developers. The current RC 4 version was released on October 25, coming perfectly on time with the PHP 7.3 timetable.

PHP 7.3-RC4 is now available to all Kinsta clients in the MyKinsta dashboard. 🤘

Or you can download the current PHP 7.3 version for your development and testing, but keep in mind that, this shouldn’t currently be used in production environments.

PHP 7.3 timetable 

PHP 7.3 timetable  (source: PHP 7.3 Preparation Tasks)

In this post, we’ll provide an overview of the features and changes that we personally consider most relevant. But you can always check the full list of features, changes and bug fixes in PHP 7.3 upgrade notes and PHP 7.3 Requests For Comments.

PHP 7.3-RC4 is now available to all Kinsta clients for testing! 🤘 Click to Tweet

What’s new in PHP with PHP 7.3?

In this post we’re covering the following PHP 7.3 changes:

Flexible Heredoc and Nowdoc Syntaxes

This is probably one of the most relevant improvements coming with PHP 7.3, and we think it deserves a little more attention. So, before diving into PHP 7.3 heredoc/nowdoc changes, we’ll provide a quick overview of this useful core feature. If you are already confident with nowdoc and heredoc, feel free to jump to the PHP 7.3 changes.

An overview of heredoc and nowdoc syntaxes

The heredoc syntax provides a way of adding a large amount of text without the need to escape things like double quotes. A heredoc starts with <<< followed by a marker, and ends with the same marker followed by a semicolon. Here is an example:

print <<<EOT
Heredoc text behaves just like a double-quoted string, without the double quotes.
EOT;

A nowdoc behaves much like a heredoc, with some exceptions:

  • The identifier is enclosed in single quotes (<<<'EOT')
  • No parsing is done inside a nowdoc

Here is an example of nowdoc:

print <<<'EOT'
Nowdocs are to single-quoted strings what heredocs are to double-quoted strings.
EOT;

Heredocs and nowdocs share the same rules regulating the usage of the closing marker:

  1. The closing marker must begin in the first column of the line
  2. The marker must follow the same naming rules as any other label in PHP: it must contain only alphanumeric characters and underscores, and must start with a non-digit character or underscore.

The PHP Manual warns:

It is very important to note that the line with the closing identifier must contain no other characters, except a semicolon (;). That means especially that the identifier may not be indented, and there may not be any spaces or tabs before or after the semicolon. It’s also important to realize that the first character before the closing identifier must be a newline as defined by the local operating system. This is \n on UNIX systems, including macOS. The closing delimiter must also be followed by a newline.

PHP 7.2 invalid syntax:

class foo {
    public $bar = <<<EOT
    bar
    EOT;
}
// Identifier must not be indented

PHP 7.2 valid syntax:

class foo {
    public $bar = <<<EOT
bar
EOT;
}

To keep it short, in PHP 7.2:

  • The closing marker may not be indented
  • The line with the closing marker may not contain characters like spaces or tabs
  • The first character before the closing marker must be a newline
  • The closing marker must be followed by a newline

It’s clear enough that heredoc and nowdoc syntaxes are quite restrictive, but PHP 7.3 may change this a little with the following improvements.

1. Allow for the closing marker to be indented and for the leading whitespace to be stripped

With PHP 7.3 we are allowed to indent the closing marker, and we can safely write the following code:

class foo {
    public $bar = <<<EOT
        bar
    EOT;
}

The indentation of the closing marker sets the amount of whitespace (or tabs) that will be stripped from each line of the body. But be careful: the closing marker should never be indented further than any other line of the body.

See the code below:

class foo {
    public $bar = <<<EOT
    bar
        EOT;
}

The code above would issue the following parse error:

Parse error: Invalid body indentation level (expecting an indentation at least ...) in %s on line %d

Stripping tabs and whitespaces allow us to indent the body of the heredoc/nowdoc to the same level of the code around, and without unnecessary whitespace before each line of the body.

We can use both tabs and spaces for indentation, but we are not allowed to use them intermixed. This means that we must use the same indentation characters for the closing marker and any lines of the body. In case of different indentation characters, we’d expect a different type of parse error (invalid indentation).

2. Remove the Trailing New Line Requirement From the Closing Marker

Currently, a new line must follow the marker in order to terminate the heredoc/nowdoc. PHP 7.3 would change this and would allow us to terminate the heredoc/nowdoc on the same line. Here is an example from the RFC:

PHP 7.2 valid syntax:

$values = [<<<END
a
b
c
END
, 'd e f'];

PHP 7.3 valid syntax:

$values = [<<<END
a
b
c
END, 'd e f'];

Anyway, be careful when choosing the name of your marker because “occasionally” you may expect an error if it matches a word you used in the body of the heredoc/nowdoc (read more on this on the RFC and GitHub).

Both proposals passed with more than 2/3 votes.

PHP 7.3 RFC

Additional Resources

Allow a trailing comma in function calls

Trailing commas (or “final commas”) are commas appended to a list of elements, parameters or properties and they come in handy in contexts where new values are appended frequently because they prevent errors due to a missing comma. In PHP trailing commas are allowed in arrays, and as of PHP 7.2 they are allowed in grouped namespaces.

As of PHP 7.3, trailing commas would be allowed in function declarations. Variadic functions provide an example of context where trailing commas are extremely useful:

foo(
    $bar,
    $baz,
);

We can use a trailing comma when we are creating an array with compact(), in order to return a formatted string with sprintf(), or when merging an array:

$newArray = array_merge(
    $arrayOne,
    $arrayTwo,
    ['foo', 'bar'],
);

Also, trailing commas would be useful for debugging:

var_dump(
    $foo,
    $bar,
    $baz,
);

And they are powerful with unset() and isset():

unset(
    $foo,
    $bar,
    $baz,
);

isset(
    $foo,
    $bar,
    $baz,
);

Trailing commas will be allowed in method calls and enclosures, as well.

Note: This change would affect function calls only. Function declaration syntax will not change. Moreover, free-standing commas, multiple trailing commas, and leading commas will not be allowed.

Additional examples can be found on the RFC page. This RFC passed with a 30 to 10 vote.

PHP 7.3 RFC

JSON_THROW_ON_ERROR

One of the most appreciated functionalities coming with PHP 7.3 provides a new way of handling JSON errors. This is not a core feature, but an addition to the JSON extension that would change the error behaviour of json_decode() and json_encode().

Currently, json_decode() returns null on error, but null can also be a valid result. This could be confusing, because

It is only possible to know if an error occurred by calling json_last_error() or json_last_error_msg(), which return the global error state in machine-readable and human-readable forms respectively. – PHP RFC

json_encode() returns FALSE on error. This is clearer because there is a specific error value. Anyway, both functions neither halt program execution on error, nor throw any warning.

With that being said, here is the proposal for PHP 7.3:

This RFC instead proposes adding a new option flag value for json_decode() and json_encode(), JSON_THROW_ON_ERROR. When passed this flag, the error behaviour of these functions is changed. The global error state is left untouched, and if an error occurs that would otherwise set it, these functions instead throw a JsonException with the message and code set to whatever json_last_error() and json_last_error_msg() would otherwise be respectively.

Here is an example showing a simple way of throwing a JSON error:

try {
    json_decode("{", false, 512, JSON_THROW_ON_ERROR);
}
catch (\JsonException $exception) {
    echo $exception->getMessage(); // echoes "Syntax error"
}

Throwing an exception upon error would give several advantages that you’ll find listed on the RFC.

Note: an invalid depth parameter passed to json_decode() outputs a warning and returns NULL. This behaviour will not be affected by JSON_THROW_ON_ERROR. Similarly, parameter parsing errors are not affected by JSON_THROW_ON_ERROR and continue to produce warnings.

This proposal passed with 23 to 0 votes.

PHP 7.3 RFC

Additional Resources

list() Reference Assignment

What Does Reference Assignment Mean?

Consider the following line:

$b = &$a;

Here $b gets the value of $a, but that value is not copied from $a to $b. In PHP we can assign a value by reference, meaning that two variables may point to the same data, and every change to any variable affects the original data. Here is an example from the PHP manual:

<?php
$a = 3;
$b = &$a; // $b is a reference to $a

print "$a\n"; // prints 3
print "$b\n"; // prints 3

Now, let’s change the value of $a:

$a = 4; // change $a

print "$a\n"; // prints 4
print "$b\n"; // prints 4 as well, since $b is a reference to $a, which has been changed

What Is The list() Construct and How It Changes With PHP 7.3

The list() language construct can be used to “assign variables as if they were in an array”, but with list() we are not currently allowed to assign variable values by reference.

PHP 7.3 should change this allowing us to assign variables by reference also with the list() construct, as shown in the following example:

$array = [1, 2];
list($a, &$b) = $array;

Which is the same as:

$array = [1, 2];
$a = $array[0];
$b =& $array[1];

The advantage of this proposal is that we could now assign multiple variables by reference, which was not currently allowed. More examples are available on the RFC. This proposal passed with 17 to 7 votes.

PHP 7.3 RFC

Additional Resources

is_countable Function

Another useful feature coming with PHP 7.3 is the is_countable() function. Up to PHP 7.2, we get an error when attempting to count() something that is not countable. For this reason, in order to avoid a warning, we are forced to add the following code:

if (is_array($foo) || $foo instanceof Countable) {
    // $foo is countable
}

This RFC proposes the function is_countable(), which returns true if the given variable is an array or it is a countable variable, false otherwise. So, the code above could be changed as follows:

if (is_countable($foo)) {
    // $foo is countable
}

This proposal passed with 25 to 0 votes.

PHP 7.3 RFC

Additional Resources

array_key_first(), array_key_last()

Currently, we can retrieve the first and the last key of an array by using reset(), end() and key() functions. Unfortunately, with these functions, there’s no way to gather the first or the last index of an array without changing its internal state. Other options usually reduce code readability and performance.
This proposal would change this scenario by adding two new functions to PHP core:

  • array_key_first()
  • array_key_last()

As of PHP 7.3, array_key_first() and array_key_last() allow to retrieve the first and the last key of a given array without affecting the internal array pointer. These new functions would allow us to write less complex code and in some cases avoid errors. See the RFC for further information and several examples.

array_key_first() and array_key_last() have been approved with 18 to 14 votes.

Note: the original RFC proposed two more functions, array_value_first() and array_value_last(), which were voted in a different poll, but haven’t been approved and won’t become parte of PHP core.

PHP 7.3 RFC

Additional Resources

Argon2 Password Hash Enhancements

Argon2 is a hashing algorithm implemented in PHP 7.2 as an alternative to the Bcrypt algorithm. PHP 7.2 introduced the PASSWORD_ARGON2I constant, available to be used in password_* functions:

password_hash('password', PASSWORD_ARGON2I);

Since its first implementation, a new variant of Argon2 has been added, so, at the time of this writing, Argon2 comes in three variants:

  • Argon2d maximizes resistance to GPU cracking attacks. It is faster and uses data-depending memory access.
  • Argon2i uses data-independent memory access, which is preferred for password hashing. It is slower as it makes more passes over the memory to protect from tradeoff attacks.
  • Argon2id is a hybrid version that combines the Argon2i approach for the first pass over memory, and the Argon2d approach for subsequent passes.

Argon2id is recommended on the Internet, except when there are good reasons to specifically prefer another variant.

Struggling with downtime and WordPress problems?

Kinsta provides an all-in-one hosting solution designed to save you time! Let us handle the nitty-gritty stuff (caching, backups, etc.), and you focus on what you do best, which is growing your business.

Check out our features

The new RFC proposes the implementation of Argon2id within the password_* functions with the new PASSWORD_ARGON2ID constant:

password_hash('password', PASSWORD_ARGON2ID);

The implementation is identical to the Argon2i implementation, and will accept the same cost factors:

  • A memory cost which defines the number of KiB that should be consumed during hashing (default values are 1<<10, or 1024 KiB, or 1 MiB)
  • A time cost that defines the number of iterations of the hashing algorithm (defaults to 2)
  • A parallelism factor, which sets the number of parallel threads that will be used during hashing (defaults to 2)

See the following code:

$options = ['memory_cost' => 1<<11, 'time_cost' => 4, 'threads' => 2];
password_hash('password', PASSWORD_ARGON2ID, $options);

More information and examples on the RFC.

PHP 7.3 RFC

Additional Resources

Deprecations

The following functions/functionalities will be deprecated with PHP 7.3 and removed not later than PHP 8.0.

Deprecate and Remove image2wbmp()

The image2wbmp() function outputs or save a WBMP version of a given image. This function takes three arguments: an image resource, a filename (the path to the saved file), and a foreground color.
As of PHP 5.0, it is identical to imagewbmp(), so this RFC proposes to deprecate and remove it.
Since PHP 7.3, each call to image2wbmp() would issue a deprecation warning. After the removal, each call would throw a fatal error.

PHP 7.3 RFC

Deprecate and Remove Case-Insensitive Constants

PHP currently supports both case-sensitive and case-insensitive constants. Anyway, case-insensitive constants are supported but considered subject to inconsistencies in functionalities and to be complex to use.
This proposal begins with the following premises:

  • class constants are always case-sensitive
  • global constants declared with const are always case-sensitive
  • constants defined with define() are case-sensitive by default

In addition, the PHP Language Reference explicitely states:

A constant is case-sensitive by default. By convention, constant identifiers are always uppercase.

That being said, this RFC proposes the following changes:

  • Deprecate calling define() with third parameter set to true – PHP 7.3
  • Deprecate accessing case-insensitive constants with a casing different from the declaration (with the exception of true, false and null) – PHP 7.3
  • Remove the possibility to declare case-insensitive constants – PHP 8.0
  • Convert true, false and null from special-cased constants into reserved keywords – PHP 8.0

PHP 7.3 RFC

Deprecate and Remove Case-Insensitive Constants.

Additional Deprecations for PHP 7.3

Here is a quick list of functionalities being deprecated in PHP 7.3. It’s not exhaustive, they’re just the deprecation proposals I personally consider more relevant. For a full list of proposed deprecations, see Deprecations for PHP 7.3.

Undocumented mbstring function aliases: there’s a number of undocumented mbstring function aliases that are duplications of equivalent functions using mb_ prefix. For example, mbereg is an alias of mb_ereg.
All these functions would be marked as deprecated and a deprecation notice would be thrown when they are encountered during compilation.

String search functions with integer needle: these functions usually operate on string needles. If a non-string needle is given, it is converted to an integer and applied as the ordinal value of a character (read more on the PHP manual). Here is an example from the RFC:

$str = "There are 10 apples";
var_dump(strpos($str, "10")); // int(10)
var_dump(strpos($str, 10));   // bool(false)

This is considered to be confusing and cause unpredictable issues because the type can change with the user data source. For this reason, the RFC proposes the issue of a deprecation warning if a non-string needle is passed to one of the following functions:

  • strpos
  • strrpos
  • stripos
  • strripos
  • strstr
  • strchr
  • strrchr
  • stristr

In PHP 8.0, the deprecation warning should be removed and the needles should be automatically converted into strings.

Still looking for that perfect WordPress host?

At Kinsta, we do hosting different than the rest. We’ve combined the fastest platform in the world (Google Cloud) with the best support team in the industry. Ready to take your site the next level?

fgetss() function and string.strip_tags stream filter: fgetss() and string.strip_tags strip tags from a stream as they read it. Both the function and the filter expose the strip_tags() functionality making the implementation of strip_tags() more complex, as a streaming state machine is required. Additionally, the RFC points out another disadvantage of these functions:

On the other hand, these functions seem to be of very little utility. strip_tags() itself, due to its limitations and known bugs, already has very few legitimate applications. There is no need to provide native support for streaming application on top of that.

So the RFC proposes to mark fgetss(), gzgetss() and SplFileObject::fgetss() as deprecated.

What Does PHP 7.3 Mean for WordPress Users?

According to the official WordPress Stats page, as of writing this, only 32.9% of WordPress users have upgraded to PHP 7 or higher. Just 4% are using PHP 7.2. You can see that a large majority of users, over 38%, are still running on PHP 5.6. What’s even scarier is that over 28.5% of users are using unsupported PHP versions. As of December 2016, WordPress.org actually bumped up their official recommendation for users from PHP 5.6 to PHP 7 or greater.

WordPress PHP versions

WordPress PHP versions

The numbers above are especially discouraging coming from a performance point of view, as PHP 7 has shown to be significantly faster. Here are a few stats:

  • Official PHP benchmarks show that PHP 7 allows the system to execute twice as many requests per second in comparison with the PHP 5.6, at almost half of the latency.
  • Christian Vigh also published a PHP performance comparison in which he found that PHP 5.2 was 400% slower than PHP 7.
  • Early benchmarks from Phoronix have shown that PHP 7.3 is about 5% faster than PHP 7.2.

We also ran our own performance benchmarks in 2018 with PHP 5.6 vs PHP 7 vs HHVM. And similarly to the benchmarks above, we saw that PHP 7.2 could execute almost three times as many transactions (requests) per second as compared to PHP 5.6.

WordPress PHP benchmarks

WordPress PHP benchmarks

  • WordPress 4.9.4 PHP 5.6 benchmark results: 49.18 req/sec
  • WordPress 4.9.4 PHP 7.0 benchmark results: 133.55 req/sec
  • WordPress 4.9.4 PHP 7.1 benchmark results: 134.24 req/sec
  • WordPress 4.9.4 PHP 7.2 benchmark results148.80 req/sec
  • WordPress 4.9.4 HHVM (3.24.2 non-repo authoritative) benchmark results: 144.76 req/sec

Many are slow to update simply because of the time involved with testing new all their third-party plugins and themes to ensure they function properly. But a lot of times, it comes down to they simply haven’t done it yet. Not sure what version of PHP you’re running? One of the easiest ways to check is to use a tool like Pingdom or Google Chrome Devtools. The first HTTP request header will typically show you the version.

Check version of PHP

Check version of PHP

This relies on the host not modifying the X-Powered-By header value. If they do, you might not see your PHP version, in which case you would need to upload a file via FTP. Or you can always reach out to your host and ask.

Updating to PHP 7.3

The final version of PHP 7.3 isn’t quite out yet, but once it is you can start testing with the pre-release version. You could test your WordPress site locally or check your scripts in an environment like Docker, which allows you to test different versions of PHP from the command line.

Or you can utilize a staging environment, as this will more closely resemble a live production site. Create a staging environment with a few simple clicks in the MyKinsta dashboard.

WordPress staging environment

WordPress staging environment

Kinsta has released PHP 7.3-RC4 in the MyKinsta dashboard so you can start testing. Please note that this is a pre-release version of PHP 7.3 and not the final release. Test thoroughly before using it on a production site.

To do so, simply change the PHP Engine for the staging site under “Tools” and you can start testing to ensure compatibility of your third-party plugins and themes.

Change to PHP 7.3 RC 4

Change to PHP 7.3 RC 4

Once we release the final version of PHP you can follow the same steps and once you confirm everything works, either change your production site over to PHP 7.3 or push your staging site to live.

Summary

As of this writing, PHP 7.3 is in its RC 4 phase, and according to the Preparation Tasks Timetable, it will be officially released in mid-December. It will bring us gifts like flexible heredocs and nowdocs, trailing commas in function calls, list() reference assignments and more. In this post, we’ve provided an overview of our favorite improvements and changes, but we would also like to know which are your favorite ones, and in which ways you’ll take advantage of them. Let us know in the comments below.

#PHP 7.3 is all about developers. Check out the new features, functionality, and bug fixes coming your way! 🤘 Click to Tweet

You can find the full list of PHP 7.3 proposals on the Requests For Comments page and GitHub’s PHP 7.3 Upgrade Notes.

If you enjoyed this article, then you'll love Kinsta’s WordPress hosting platform. Turbocharge your website and get 24x7 support from our veteran WordPress team. Our Google Cloud powered infrastructure focuses on auto-scaling, performance, and security. Let us show you the Kinsta difference! Check out our plans

Hand-picked related articles

Comment policy: We love comments and appreciate the time that readers spend to share ideas and give feedback. However, all comments are manually moderated and those deemed to be spam or solely promotional will be deleted.
  1. Gravatar for this comment's author
    Georgi August 31, 2018 at 1:20 am

    That’s all nice info copied from php.org but the article doesn’t contain the useful info where PHP 7.3 will be available at Kinsta?

    1. Gravatar for this comment's author
      Brian Jackson August 31, 2018 at 8:46 am

      Hey Georgi!
      It’s toward the bottom :)

      Kinsta will be releasing PHP 7.3 as soon as it’s available and has been fully tested by our sysadmin team. We usually don’t put dates on software releases because the PHP release timeline could be delayed or pushed back.

      You can guarantee though once PHP 7.3 is officially released our team will be on it!

Leave a Reply

Use WordPress?

Use WordPress?

Join 20,000+ others who get our FREE weekly newsletter with WordPress tips on how to drive more traffic and revenue to your business!

Consent

You have Successfully Subscribed!

Send this to a friend