📜 ⬆️ ⬇️

What's new in PHP 7.2?

Despite the fact that we are actively working with Python and Go, still a significant part of our server code is written in PHP. Therefore, we are closely following all the innovations of the language. Less than a year has passed since the release of the previous minor version, and now the last beta release is scheduled for August 17th. It is not recommended to use it in production yet, but you can already download the docker image . It's time to figure out what has changed in the new version of the language.



Content



Optimization


Opcache adds global optimization based on data flow analysis using SSA (Static single assignment form): Sparse Conditional Constant Propagation (SCCP), dead code elimination (DCE) removal, and deletion of unused local variables.


Optimized the in_array() built-in function by searching for a hash in an inverted array.


New functionality


Added the ability to download extensions by name ( RFC )


Previously, extension= and zend_extension= in the php.ini file contained paths to the extension file.
But, unfortunately, the file name depended on the platform. For example, in unix-like systems, it was built as <extension-name>.<suffix> , where suffix is .so on all systems except HP-UX , where it is sl . On Windows, the file name is generated as php_<extension-name>.dll . All this caused a lot of mistakes.


Now you can write:


 extension=bz2 zend_extension=xdebug 

And the necessary extensions will be loaded depending on the OS.


This mechanism will work when installing the extension and zend_extension in the ini-file, as well as an argument to the dl() function.


But the absolute paths will still need to be specified with the -z flag in CLI mode, as well as with the absolute path. The following example will not work:


extension=/path/to/extensions/bz2


Added ability to overload abstract functions ( RFC )


Now you can reload abstract functions in the same way as regular functions:


 abstract class A { abstract function bar(stdClass $x); } abstract class B extends A { abstract function bar($x): stdClass; } class C extends B { function bar($x): stdClass{} } 

Before PHP 7.2, an error of the form was issued:


Fatal error: Can't inherit abstract function A::bar() (previously declared abstract in B)


Forbidden number_format () return -0 ( RFC )


The call number_format(-0.00) returned string(1) “0” , however number_format(-0.01) returned string(2) “-0” . Now, 0 without a sign will be returned.


Added the ability to convert numbered keys when casting object / array ( RFC ) types


Background:


In PHP, there are two types of data that contain a key / value. The first is arrays, which can contain keys in the form of strings or numbers. Moreover, if the string satisfies the rule /^(0|(-?[1-9][0-9]*))$/ and it is rather small PHP_INT_MIN ≤ n ≤ PHP_INT_MAX , then it is converted into a numeric key.


The second type is objects in which numeric keys are not allowed, and keys are converted to strings.


In the Zend Engine, they are represented as a single HashTable structure.


Now it is fixed.


Let's look at a couple of examples:


 $obj = new stdClass; $obj->{'0'} = 1; $obj->{'1'} = 2; $obj->{'2'} = 3; $arr = (array) $obj; var_dump($arr); // ,    / var_dump($arr[1]); //     .  PHP 7.2  . 

 $arr = [0 => 1, 1 => 2, 2 => 3]; $obj = (object)$arr; var_dump($obj); // ,    / var_dump($obj->{'0'}); //     .  PHP 7.2  . 

It is forbidden to pass null as a parameter to get_class () ( RFC )


When null is passed as the get_class() parameter inside the class context, the behavior of the function can be quite unexpected:


 class Foo { function bar($repository) { $result = $repository->find(100); return get_class($result); } } 

If $result contains a valid object returned from the repository, the result of the function is the class name of this object.


If $result is null , the output will be the class context from which get_class() is called, in this case Foo .


This feature violates the principle of least surprise: “if the necessary function has a high coefficient of surprise, this function may need to be redesigned”.
Now a warning will be issued:
Warning: get_class() expects parameter 1 to be object, null given in %s on line %d
If you want to keep the old behavior, you have to rewrite the code:


 // : $x = get_class($some_value_that_may_be_null); // : if ($some_value_that_may_be_null === null) { $x = get_class(); } else { $x = get_class($some_value_that_may_be_null); } 

Calling Count with a non-counting parameter ( RFC )


Now, a call to count() with a parameter that is scalar, null, or an object that does not implement the Countable interface will issue a Warning .


The possibility of expanding the parameter type ( RFC )


One of the most hotly discussed changes is the possibility not to specify the type of the parameter in the heir. Thus, the heir will be able to accept a parameter of any type.


 class ArrayClass { public function foo(array $foo) { /* ... */ } } class EverythingClass extends ArrayClass { public function foo($foo) { /* ... */ } } 

Before PHP 7.2, an error was returned:


 Warning: Declaration of EverythingClass::foo($foo) should be compatible with ArrayClass::foo(array $foo) in %s on line 18 

In the pull request, opinions were divided.
Some said:


"Of course, let's send SOLID to hell. Who is Barbara Liskov ??? Some crazy woman? Of course! Let's allow breaking principles and ideas."

Others believe that:


"Restrictions like the principle of single responsibility should be implemented not at the level of the language, but in the application code. And now the letter L in SOLID will be at the discretion of the developer."

Added ability to specify a comma at the end of grouped namespaces ( RFC )


 //       $array = [1, 2, 3,]; //      use Foo\Bar\{ Foo, Bar, Baz, }; 

It was planned to add such an opportunity for other lists, but at the voting stage they were canceled and will still return a Parse error :


 //     fooCall($arg1, $arg2, $arg3,); //    class Foo implements FooInterface, BarInterface, BazInterface, { //   use FooTrait, BarTrait, BazTrait, ; //     const A = 1010, B = 1021, C = 1032, D = 1043, ; protected $a = 'foo', $b = 'bar', $c = 'baz', ; private $blah, ; //     function something(FooBarBazInterface $in, FooBarBazInterface $out,) : bool { } } //         $foo = function ($bar) use ( $a, $b, $c, ) { // . . . }; 

Implemented socket_getaddrinfo ( RFC ) family of functions


Now, information from getaddrinfo() implemented in C will be available from PHP. It is implemented in C. This is the missing function for the current socket library. When working with different networks, it would be useful to allow libc tell us which connection / listening methods would be most appropriate given the set of hints.


Four functions were approved:


 socket_addrinfo_lookup(string node[, mixed service, array hints]) : array socket_addrinfo_connect(resource $addrinfo) : resource socket_addrinfo_bind(resource $addrinfo) : resource socket_addrinfo_explain(resource $addrinfo) : array 

Improved TLS constants ( RFC )


Now:



Object typehint ( RFC )


Added new hint type: object


 function acceptsObject(object $obj) { // ... } acceptsObject(json_decode('{}')); acceptsObject(new \MyObject()); acceptsObject(" "); function correctFunction() : object { $obj = json_decode('{}'); return $obj; } //   function errorFunction() : object { return []; } 

LDAP EXOP ( RFC )


Added functions for using advanced LDAP operations in php-ldap.


 //  EXOP whoami     $identity if (ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, $identity)) { echo "Connected as $identity\n"; } else { echo "Operation failed\n"; } //    ,   : $r = ldap_exop($link, LDAP_EXOP_WHO_AM_I); if (($r !== FALSE) && ldap_parse_exop($link, $r, $retdata)) { echo "Connected as $retdata\n"; } else { echo "Operation failed\n"; } //     : if (ldap_exop_whoami($link, $identity)) { echo "Connected as $identity\n"; } else { echo "Operation failed\n"; } //    : if (ldap_exop_passwd($link, 'uid=johndoe,dc=example,dc=com', '', 'newpassword')) { echo "Password changed\n"; } else { echo "Operation failed\n"; } 

Libsodium ( RFC ) added to PHP core


Libsodium is a modern cryptographic library that offers authenticated encryption, high-speed cryptography with elliptic curves, and much more. Unlike other cryptographic standards (which are a set of cryptographic primitives, for example, WebCrypto), libsodium includes carefully selected algorithms implemented by security experts. This will help avoid vulnerabilities in third-party channels.


Added algorithm Argon2 in password hashing ( RFC )


Argon2 is a modern simple algorithm aimed at high speed of memory filling and efficient use of several computational blocks.


HashContext as Object ( RFC )


Since PHP5, the preferred structure for storing internal data has been objects. For some reason, the Hash extension used resources for this. This RFC is trying to correct a misunderstanding by transferring the Hash extension to store internal data in the form of objects.


Examples of using the resource as an internal representation:


 resource hash_copy ( resource $context ) resource hash_init ( string $algo [, int $options = 0 [, string $key = NULL ]] ) 

The internal representation is converted from a resource to an object. Existing code should continue to work, if it does not use explicit is_resource () checks, these checks can be easily replaced with is_resource | is_object.


Added PDO Prepared statements ( RFC ) debugger


 $db = new PDO(...); $stmt = $db->query('SELECT 1'); var_dump($stmt->activeQueryString()); // => string(8) "SELECT 1" $stmt = $db->prepare('SELECT :string'); $stmt->bindValue(':string', 'foo'); //      var_dump($stmt->activeQueryString()); // => string(14) "SELECT :string" //      $stmt->execute(); var_dump($stmt->activeQueryString()); // => string(11) "SELECT 'foo'" 

Added PDO Prepared statements v2 ( RFC ) debugger


 $calories = 150; $colour = 'red'; $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?'); $sth->bindParam(1, $calories, PDO::PARAM_INT); $sth->bindValue(2, $colour, PDO::PARAM_STR); $sth->execute(); $sth->debugDumpParams(); /* : SQL: [82] SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ? Sent SQL: [88] SELECT name, colour, calories FROM fruit WHERE calories < 150 AND colour = 'red' Params: 2 Key: Position #0: paramno=0 name=[0] "" is_param=1 param_type=1 Key: Position #1: paramno=1 name=[0] "" is_param=1 param_type=2 */ 

Extended String Types for PDO ( RFC )


 $db->quote('ĂĽber', PDO::PARAM_STR | PDO::PARAM_STR_NATL); // N'ĂĽber' $db->quote('A'); // 'A' $db->setAttribute(PDO::ATTR_DEFAULT_STR_PARAM, PDO::PARAM_STR_NATL); $db->quote('ĂĽber'); // N'ĂĽber' $db->quote('A', PDO::PARAM_STR | PDO::PARAM_STR_CHAR); // 'A' 

Added JSON_INVALID_UTF8_IGNORE and JSON_INVALID_UTF8_SUBSTITUTE ( Request ) options


For the json_encode / json_decode , new JSON_INVALID_UTF8_IGNORE and JSON_INVALID_UTF8_SUBSTITUTE options have JSON_INVALID_UTF8_IGNORE JSON_INVALID_UTF8_SUBSTITUTE to ignore or replace invalid UTF-8 byte sequences.


Removed from PHP 7.2


The following functionality has been deprecated and has been removed.


Removed strings without quotes (bare word) ( RFC )


E_WARNING are now called E_WARNING . In PHP2, such lines caused a Syntax error , but in PHP3, the beta behavior was changed.
For example:


 $foo = flase; // ,     E_NOTICE,   . // ... if ( $foo ) { var_dump($foo); // string(5) "flase" } 

Transfer mcrypt to PECL


The mcrypt extension, deprecated in PHP 7.1, has been moved to PECL.


Declared deprecated in PHP 7.2 ( RFC )


The following functionality is deprecated and is no longer recommended for use.
This functionality will be removed in version 8.0.


Obsolete __autoload


The __autoload function __autoload been replaced by spl_autoload_register back in version 5.1.
The main advantage of spl_autoload_register is the ability to use multiple autoloaders. Deprecation notice will now be thrown Deprecation notice at compile time.


Obsolete png2wbmp () and jpeg2wbmp ()


Png2wbmp() and jpeg2wbmp() are the only functions that change the format of images that can be called directly, available in ext / gd , which makes them rather isolated, since libgd does not offer such functions. In addition, WBMP was invented to support WAP , which is now obsolete. Deprecation notice will now be thrown.


Obsolete $ php_errormsg


The variable $php_errormsg is created in the local scope when a non-fatal error occurs, if the track_errors parameter track_errors on (disabled by default) and the error is not intercepted by any error handler.


Besides the fact that the behavior depended on the ini-file settings, it was also magical. The error_get_last function provides a cleaner way to get the latest error. With PHP 7, the error_clear_last function is error_clear_last , so all possible uses of $php_errormsg without scoping.


Outdated create_function ()


create_function() is a thin shell around the eval() language construct that allows you to create a function with the generated name, argument list, and body as string arguments. Before the introduction of closures in PHP 5.3, it provided a way to create something similar to the lambda function.


Due to the nature of the work, create_function() , in addition to a potential source of security problems, has very poor performance and memory usage characteristics. The use of real closures in all respects is preferable.


Obsolete mbstring.func_overload


The mbstring.func_overload parameter in the ini-file allows replacing a certain subset of string functions with analogues with the mbstring extension. For example, strlen() will no longer return the length of the string in bytes, instead it returns the length in characters according to the currently selected internal encoding.


This means that code using mbstring.func_overload not compatible with code written under the assumption that basic string operations work fine. Some libraries directly prohibit func_overload (for example, symfony), other libraries stop working. Code that wants to support func_overload should conditionally switch between ordinary string functions and mbstring functions with 8-bit encoding (usually only libraries for cryptography try to do this).
Deprecation notice will now be thrown if mbstring.func_overload contains a non-zero value.


Deprecated (unset) cast


Cast (unset) turns the value into null. This means that (unset) expr is just an expression that always returns null and has no other side effects.
In addition to being useless, this behavior is only confusing, since many people reasonably assume that (unset) $a will behave like unset($a) , but in reality this does not happen.
Deprecation notice will now be thrown Deprecation notice at compile time.


The parse_str () function is deprecated without a second argument.


The parse_str() function parses the URL string and assigns values ​​to variables in the current context (or puts it into an array if the result parameter is specified).


It was highly recommended not to use this function without the result parameter, because the dynamic creation of variables in the scope of a function leads to exactly the same problems as register_globals. Deprecation notice now thrown if the result parameter is not passed.


The gmp_random () function is deprecated.


The gmp_random() function generates a random number. The number will be in the range of zero before the product of the number limiter and the number of bits in the limb. If the limiter number is negative, a negative result will be returned.


Limb is an internal GMP mechanism. Technically, this is a part of a number that fits into one machine word. The number of bits in it may vary in different systems. Basically it is either 16 or 32, but this is not guaranteed. This happens because the GMP / MPIR implementation is not available to the user. Thus, the use of this function requires guessing the size of the Limb and may depend on the platform.


To fix this, in PHP 5.6, the gmp_random_bits() and gmp_random_range() functions were added, which allow you to precisely control the range of random numbers used. These functions should always be preferable to gmp_random() .
Now, when calling gmp_random() Deprecation notice thrown.


The each () function is deprecated.


The each() function can be used to iterate over an array, like foreach . In each call, it returns an array with the current key and value, and advances the pointer to the internal array to the next position. A typical use presented in the manual is as follows:


 reset($array); while (list($key, $val) = each($array)) { echo "$key => $val\n"; } 

The each function is inferior to foreach almost everything, among other things, it is 10 times slower.
Support for this feature poses a problem for some language changes. For example, in a warning for an invalid array container ( RFC ), list() ) had to be excluded, because the typical use of each relies on the fact that you can access array shifts to false without warning.


Now, Deprecation warning thrown when you first call each , because it is most often used in a loop.


Deprecated assert () function with string argument


The assert() function has two modes of operation: if something other than a string is passed, it will check that the value is true. If a string was passed, it will be run via eval() , and assert will check the validity of the result of eval() .


The reason for this behavior is that prior to PHP 7, this was the only way to prevent expression evaluation. Starting with PHP 7, the zend.assertions option in the ini file can be used to avoid evaluating expressions. Thus, it is no longer necessary to support the implicit evaluation of string arguments.


Using assert($value) to validate the value opens a remote code execution vulnerability if there is a possibility that $value will be a string.
Deprecation notice now thrown if assert() used with a string argument.


Outdated $ errcontext argument in error handler


Error handlers defined with set_error_handler() are passed as the last argument to $errcontext . This argument is an array containing all local variables in the location where the error was generated.


This feature is difficult to optimize because $errcontext can be used to change all references and objects in the current scope. This functionality is almost never used. If you want to check the status variables at the location of the error, you must use a debugger.


Note that the error context contains only local variables. Backtrace errors, including $this and function arguments, will remain available through debug_backtrace() .


In this case, it is impossible to throw out the Deprecation warning , so this functionality will simply be marked outdated in the documentation.


Constant INTL_IDNA_VARIANT_2003 Obsolete


In PHP 7.2, the constant INTL_IDNA_VARIANT_2003 is deprecated.
In PHP 7.4, idn_to_ascii() and idn_to_utf8() will be changed, in which the default $variant parameter will be INTL_IDNA_VARIANT_UTS46.
In PHP 8.0, support for INTL_IDNA_VARIANT_2003 will be removed.


Declared obsolete casting (binary) and b "" literals ( RFC )


Type (binary) and support for the b prefix were added in PHP 5.2.1 for compatibility with PHP 6 , but this version never appeared, and it is unknown whether there will ever be any attempt to implement binary strings. However, they are still accepted by the language scanner, although they are ignored.
Deprecation notice now thrown when using these castes.


Especially for version 7.2, I prepared a repository - " What's new in PHP ", which describes changes in PHP versions starting from 5.


The list in English can be found in the sources:
https://github.com/php/php-src/blob/PHP-7.2/UPGRADING
https://wiki.php.net/rfc#php_next_72


Try new version online:
https://3v4l.org/


As we see, global change is not enough.
And how do you feel about the changes in PHP? What feature did you like the most?


')

Source: https://habr.com/ru/post/335584/


All Articles