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.
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.
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 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 results: 148.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.
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.
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.
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?
Most of the problem with the slow pace of upgrades is that most hosts won’t get their acts together. It’s usually not the site owner’s fault.
Definitely agree Casey. Hosts are a huge part of the problem! However there are good ones out there. We’ve offered PHP 7 here at Kinsta since the first stable release in 2015. We then followed up with PHP 7.1 February of this year, and will be doing the same for PHP 7.2.
Excellent post!
A lot of plugins will need to update, because of the use of create_function().
Thx for this summary. But I found a mistake. The section “Trailing commas in list syntax” lists several options where we can use trailing commas in PHP 7.2 but the list is wrong. Only “Grouped namepaces only” are accepted and implemented.
Thank you for pointing it out Hans.
> gmp_random_rage()
GIVE ME RANDOM NUMBER ALREADY!!!
For rolling out PHP 7.2, I think you mean December 1st. There is no 31st of November.
And thank you for adding that capability so quickly. Always staying in the forefront :-)
Oh wow, thanks Dave. I guess we need some more coffee over here. That has been fixed. The release of PHP 7.2 is set for tomorrow, December 1st :)
Great post. Thank you, Sir.
Yes, it is time to speed up our sites, with new PHP 7.2.
By the way, why you don’t use discuss anymore?
With kind regards.
We moved away from Disqus mainly due to SEO purposes and indexing of comments.
Excellent news, I really enjoy PHP upgrades, and much old versions like 5- use to create some issues and loading delay.
Definitely exciting news! Each new version of PHP has shown performance improvements over the last.
And here I am, being forced to use 5.2.* for some legacy projects…
Short array syntax? Nope.
array_column? Nope.
But for my own projects, I’ve just upgraded to 7.1 (from 5.6) and the performance gain is sweeet!
Hey Peter,
Yes there will always be those types of projects :) That’s why we are still offering PHP 5.6 (lowest supported version). And yes, the performance gains from 5.6 to 7+ are definitely significant!
Object Type Hinting is really welcome, but the Type Widening makes no sense to me…
What I really need every single day is the opposit:
interface GeneralInterface {
public function foo() : GeneralInterface;
}
class ConcreteClass implements GeneralInterface {
public function foo() : ConcreteClass {
// …
return $this;
}
}
Type Narrowing??? Since ConcreteClass implements GeneralInterface, so the instance of ConcreteClass will be the instance of GeneralInterface too. So why can’t I be more strict and specific in the implementation/extension?
I wanted to move my site to PHP 7.2, the stuff here really helped me make the right decision.
Hello! I just update to PHP 7.2, unfortunately I got this 2 lines on ‘Add New Plugin’ in the admin dashboard “stdClass::$plugin in /home/mediamak/public_html/wp-includes/class-wp-list-util.php on line 150”.
I came here with keyword ‘the best setting for PHP 7.2’ and I believe that someone will help me on this issue. I can’t even update my plugin as well as view its detail, it is the only one popular seo in the world. The rest looks fine.
Is it because of PHP 7.2? So far, I did not find any solution yet even almost 3 days I am searching about this on Google.
Any help would be appreciated. I also understand with simple English. Thank you.
Glad to learn more.
Hey Ismail!
Sounds like you might be running a plugin that isn’t compatible with PHP 7.2. We suggest disabling all your plugins temporarily and re-enabling them one by one until you find the culprit.
Really informative article, thanks a lot!