PHP 7.2 has been officially released as of November 30. The release has new features, functions, and improvements that will allow us to write better code. In this post, we’ll introduce some of the most interesting language features with PHP 7.2.

Update: PHP 8.0 is now available to all Kinsta clients.

You can see the full list of changes on the Requests For Comments page.

Core Improvements

Argument type declarations

Since PHP 5 we are allowed to specify in a function’s declaration the argument type that is expected to be passed. If the given value is of an incorrect type, then PHP throws an error.

Argument type declarations (also known as type hints) specify the type of a variable that is expected to be passed to a function or class method.

Here is an example:

class MyClass {
	public $var = 'Hello World';
}

$myclass = new MyClass;

function test(MyClass $myclass){
	return $myclass->var;
}

echo test($myclass);

In this code, the test function expects an instanceof MyClass. An incorrect data type would result in the following fatal error:

Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of MyClass, string given, called in /app/index.php on line 12 and defined in /app/index.php:8

Since PHP 7.2 type hints can be used with the object data type, and this improvement allows to declare a generic object as argument of a function or method. Here is an example:

class MyClass {
	public $var = '';
}

class FirstChild extends MyClass {
	public $var = 'My name is Jim';
}
class SecondChild extends MyClass {
	public $var = 'My name is John';
}

$firstchild = new FirstChild;
$secondchild = new SecondChild;

function test(object $arg) {
	return $arg->var;
}

echo test($firstchild);

echo test($secondchild);

In this example we’ve called the test function twice, passing a different object at each call. This was not possible in previous PHP versions.

Docker commands
Testing type hints with PHP 7.0 and PHP 7.2 in Docker

Object return type declarations

If argument type declarations specify the expected type for a function’s arguments, return type declarations specifies the expected type of the returning value.

Return type declarations specify the type of a variable that is expected to be returned by a function.

As of PHP 7.2 we are allowed to use return type declarations for the object data type. Here is an example:

class MyClass {
	public $var = 'Hello World';
}

$myclass = new MyClass;

function test(MyClass $arg) : object {
	return $arg;
}

echo test($myclass)->var;

Previous PHP versions throw the following fatal error:

Fatal error: Uncaught TypeError: Return value of test() must be an instance of object, instance of MyClass returned in /app/index.php:10

Of course, in PHP 7.2 this code echoes ‘Hello World’.

Parameter Type Widening

PHP currently does not allow any variance of parameter types between child classes and their parent classes or interfaces. What does that mean?
Consider the following code:

<?php
class MyClass {
	public function myFunction(array $myarray) { /* ... */ }
}

class MyChildClass extends MyClass {
	public function myFunction($myarray) { /* ... */ }
}

Here we’ve omitted the parameter type in the subclass. In PHP 7.0 this code produces the following warning:

Warning: Declaration of MyChildClass::myFunction($myarray) should be compatible with MyClass::myFunction(array $myarray) in %s on line 8

Since PHP 7.2, we are allowed to omit a type in a subclass without breaking any code. This proposal will allow us to upgrade classes to use type hints in libraries without being required to update all subclasses.

Trailing commas in list syntax

A trailing comma after the last item in arrays is valid syntax in PHP, and sometimes it’s encouraged in order to easily append new items and avoid parse errors due to a missing comma. Since PHP 7.2 we are allowed to use trailing commas in grouped namespaces.

See Trailing Commas In List Syntax for a closer view at this RFC and some examples of code.

Security Improvements

Argon2 in password hash

Argon2 is a powerful hashing algorithm which was selected as the winner of 2015 Password Hashing Competition, and PHP 7.2 will bring it to us as a secure alternative to the Bcrypt algorithm.
The new PHP version introduces the PASSWORD_ARGON2I constant, that can now be used in password_* functions:

password_hash('password', PASSWORD_ARGON2I);

Unlike Bcrypt, which takes only one cost factor, Argon2 takes three cost factors distinguished as follows:

  • 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)

Three new constants define default cost factors:

  • PASSWORD_ARGON2_DEFAULT_MEMORY_COST
  • PASSWORD_ARGON2_DEFAULT_TIME_COST
  • PASSWORD_ARGON2_DEFAULT_THREADS

Here is an example:

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

See Argon2 Password Hash for more information.

Libsodium as part of PHP Core

Starting from version 7.2, PHP includes the Sodium library into the core. Libsodium is a cross-platform and cross-languages library for encryption, decryption, signatures, password hashing and more.
The library was previously available through PECL.
For a documented list of Libsodium functions, refer to the library Quick Start Guide.
See also PHP 7.2: The First Programming Language to Add Modern Cryptography to its Standard Library.

Deprecations

Here is a list of PHP 7.2 deprecated functions and features that will be removed no later that PHP 8.0:

The __autoload function has been superseded by spl_autoload_register in PHP 5.1. Now a deprecation notice would be thrown when it’s encountered during compilation.

The $php_errormsg variable is created in the local scope when a non-fatal error is thrown. Since PHP 7.2 error_get_last and error_clear_last should be used instead.

create_function() allows the creation of a function with a generated function name, a list of arguments and body code provided as arguments. Due to security issues and bad performance, it has been marked as deprecated and the usage of enclosures is encouraged instead.

mbstring.func_overload ini setting set to a non-zero value has been marked as deprecated.

(unset) cast is an expression that always returns null and is considered useless.

parse_str() parses a query string into an array if the second argument is provided, or into the local symbol table if it is not used. As dinamically setting variables in function’s scope is discouraged for security reasons, the use of parse_str() without the second argument will throw a deprecation notice.

gmp_random() is considered to be platform dependent and will be deprecated. Use gmp_random_bits() and gmp_random_rage() instead.

each() is used to iterate over an array much like foreach(), but foreach() is preferable for several reasons, including being 10 times faster. Now a deprecation will be thrown on the first call in a loop.

The assert() function checks the given assertion and takes appropriate actions if the result is FALSE. The usage of assert() with string argument is now deprecated as it opens an RCE vulnerability. The zend.assertion ini option can be used to prevent evaluation of assertion expressions.

$errcontext is an array containing the local variables existing at the time an error is generated. It’s passed as the last argument to error handlers set with the set_error_handler() function.

What Does PHP 7.2 Mean for WordPress Users?

According to the official WordPress Stats page, as of writing this, only 19.8% of WordPress users have upgraded to PHP 7. And only 5% are using PHP 7.1. You can see that a large majority of users, over 40%, are still running on PHP 5.6. What’s even scarier is that over 39% 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 7.1 stats
WordPress PHP 7.1 stats

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.

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 benchmarks
WordPress 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 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.2

PHP 7.2 isn’t quite out yet, but once it is you can start testing. 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. Kinsta made PHP 7.2 available for all clients on December 4th. You can easily create a staging environment with a single click.

Test PHP 7.2 in staging environment
Test PHP 7.2 in staging environment

Simply one-click 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. Once you confirm everything works, you can either change your production site over to PHP 7.2 or push your staging site to live.

Change to PHP 7.2
Change to PHP 7.2

Conclusions

Are you ready to switch to PHP 7.2? Hopefully, by now you have at least made the transition to PHP 7. If you haven’t now is a good time to start testing. So, upgrade your scripts, check your code and let us know your first impressions of PHP 7.2.

Recommended reading: Is PHP dead?

Carlo Daniele Kinsta

Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.