Elérhető szervereinken a PHP 7.4 - Néhány szó a tulajdonságairól
Posted by netkey admin on 2020.09.03 03:38 PM |
|
Features, Deprecations, Speed PHP 7.4 (official release) is available to all Netkey clients in the Netkey Webhosting Panel in Website settings sections. Even if PHP 7.4 significantly boosts performance and improves code readability, PHP 8 will be the real milestone for PHP performance, as the proposal for JIT inclusion has already been approved. Anyway, today we’re going through some of the most interesting features and changes we’re expecting with PHP 7.4. Just for the record, these were the important dates for the 7.4 version:
You can check out the full list of features and additions on the official RFC page. Table of Contents
What’s New in PHP with PHP 7.4?In this post we’re covering several changes and features that should be added to the language with the final release of PHP 7.4:
Forget array_merge: PHP 7.4 Brings Spread Operator in Array ExpressionAvailable since PHP 5.6, argument unpacking is a syntax for unpacking arrays and Traversables into argument lists. To unpack an array or a Traversable, it has to be prepended by … (3 dots), as shown in the following example: function test(...$args) { var_dump($args); } test(1, 2, 3); Now this PHP 7.4 RFC proposes to extend this feature to array definitions: $arr = [...$args]; The first declared benefit of Spread Operator in array expression is all about performance. In fact, the RFC doc states: A significant advantage of Spread operator is that it supports any traversable objects, while the array_merge function only supports arrays. Here is an example of argument unpacking in array expression: $parts = ['apple', 'pear']; $fruits = ['banana', 'orange', ...$parts, 'watermelon']; var_dump($fruits); If you run this code with in PHP 7.3 or earlier, PHP throws a Parse error: Parse error: syntax error, unexpected '...' (T_ELLIPSIS), expecting ']' in /app/spread-operator.php on line 3 Instead, PHP 7.4 would return an array: array(5) { [0]=> string(6) "banana" [1]=> string(6) "orange" [2]=> string(5) "apple" [3]=> string(4) "pear" [4]=> string(10) "watermelon" } The RFC states that we can expand the same array multiple times. Moreover, we can use the Spread Operator syntax everywhere in the array, as normal elements can be added before or after the spread operator. So the following code will work as we may expect: $arr1 = [1, 2, 3]; $arr2 = [4, 5, 6]; $arr3 = [...$arr1, ...$arr2]; $arr4 = [...$arr1, ...$arr3, 7, 8, 9]; It’s also possible to unpack arrays returned by a function directly into a new array: function buildArray(){ return ['red', 'green', 'blue']; } $arr1 = [...buildArray(), 'pink', 'violet', 'yellow'];
array(6) { [0]=> string(3) "red" [1]=> string(5) "green" [2]=> string(4) "blue" [3]=> string(4) "pink" [4]=> string(6) "violet" [5]=> string(6) "yellow" } We can also use the generator syntax: function generator() { for ($i = 3; $i <= 5; $i++) { yield $i; } } $arr1 = [0, 1, 2, ...generator()];
$arr1 = ['red', 'green', 'blue']; $arr2 = [...&$arr1]; If we’d try to unpack an array by reference, PHP throws the following Parse error: Parse error: syntax error, unexpected '&' in /app/spread-operator.php on line 3 Anyway, if the elements of the first array are stored by reference, they are stored by reference in the second array, as well. Here is an example: $arr0 = 'red'; $arr1 = [&$arr0, 'green', 'blue']; $arr2 = ['white', ...$arr1, 'black']; And here is what we get with PHP 7.4: array(5) { [0]=> string(5) "white" [1]=> &string(3) "red" [2]=> string(5) "green" [3]=> string(4) "blue" [4]=> string(5) "black" } The Spread operator proposal passed with 43 to 1 votes. Arrow Functions 2.0 (Short Closures)In PHP, anonymous functions are considered to be quite verbose and difficult to implement and maintain. This RFC proposes the introduction of the shorter and clearer syntax of the arrow functions (or short closures), that should allow us to clean up significantly our PHP code. Consider the following example: function cube($n){ return ($n * $n * $n); } $a = [1, 2, 3, 4, 5]; $b = array_map('cube', $a); print_r($b); PHP 7.4 allows to use a more concise syntax, and the function above could be rewritten as follows: $a = [1, 2, 3, 4, 5]; $b = array_map(fn($n) => $n * $n * $n, $a); print_r($b); Currently, anonymous functions (closures) can inherit variables defined in the parent scope thanks to the use language construct, as shown below: $factor = 10; $calc = function($num) use($factor){ return $num * $factor; }; But with PHP 7.4, variables defined in the parent scope are implicitly captured by value (implicit by-value scope binding). So we can write the whole function seen above on a single line: $factor = 10; $calc = fn($num) => $num * $factor; The variable defined in the parent scope can be used in the arrow function exactly as if we were using use($var), and it’s not possible to modify a variable from the parent scope. The new syntax is a great improvement to the language as it allows us to build more readable and maintainable code. We can also use parameter and return types, default values, variable-length argument lists (variadic functions), we can pass and return by reference, etc. Finally, short closures can also be used in class methods, and they can make use of the $this variable just like regular closures. This RFC has been approved with 51 to 8 votes, so we can expect it to be part of PHP 7.4 additions.
Null Coalescing Assignment Operator
Added with PHP 7, the coalesce operator (??) comes in handy when we need to use a ternary operator in conjunction with isset(). It returns the first operand if it exists and is not NULL. Otherwise, it returns the second operand. Here is an example: $username = $_GET['user'] ?? ‘nobody'; What this code does is pretty straightforward: it fetches the request parameter and sets a default value if it doesn’t exist. The meaning of that line is clear, but what if we had much longer variable names as in this example from the RFC? $this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value'; In the long run, this code could be a bit difficult to maintain. So, aiming to help developers to write more intuitive code, this RFC proposes the introduction of the null coalescing assignment operator (??=). So, instead of writing the previous code, we could write the following: $this->request->data['comments']['user_id'] ??= ‘value’; If the value of the left-hand parameter is null, then the value of the right-hand parameter is used. This proposal has been approved with 37 to 4 votes. Typed Properties 2.0Argument type declarations, or type hints, allow to specify the type of a variable that is expected to be passed to a function or a class method. Type hints are a feature available since PHP 5, and since PHP 7.2 we can use them with the object data type. Now PHP 7.4 brings type hinting a step forward by adding support for first-class property type declarations. Here is a very basic example: class User { public int $id; public string $name; } All types are supported, with the exception of void and callable: public int $scalarType; protected ClassName $classType; private ?ClassName $nullableClassType; The RFC explains the reason why void and callable are not supported:
So we can safely use bool, int, float, string, array, object, iterable, self, parent, any class or interface name, and nullable types (?type). Types can be used on static properties: public static iterable $staticProp; They are also allowed with the var notation: var bool $flag; It’s possible to set default property values, which of course must match the declared property type, but only nullable properties can have a default null value: public string $str = "foo"; public ?string $nullableStr = null; The same type applies to all properties in a single declaration: public float $x, $y; What happens if we make an error on the property type? Consider the following code: class User { public int $id; public string $name; } $user = new User; $user->id = 10; $user->name = []; In the code above, we declared a string property type, but we set an array as property value. In such scenario, we get the following Fatal error: Fatal error: Uncaught TypeError: Typed property User::$name must be string, array used in /app/types.php:9 This RFC has been approved with 70 to 1 votes. Weak References
With this RFC, PHP 7.4 introduces the WeakReference class, which allows programmers to retain a reference to an object that doesn’t prevent the object itself from being destroyed. Currently, PHP supports Weak References by using an extention like pecl-weakref. Anyway, the new API is different from the documented WeakRef class. Here is an example from the author of this proposal, Nikita Popov: $object = new stdClass; $weakRef = WeakReference::create($object); var_dump($weakRef->get()); unset($object); var_dump($weakRef->get()); The first var_dump prints object(stdClass)#1 (0) {}, while the second var_dump prints NULL, as the referenced object has been destroyed. This RFC passed with 28 to 5 votes. Covariant Returns and Contravariant ParametersVariance is a property of class hierarchies describing how the types of a type constructor affect subtypes. In general, a type constructor can be:
Currently, PHP has mostly invariant parameter and return types, with few exceptions. This RFC proposes to allow covariance and contravariance on parameter types and return types, also providing several examples of code. Here is an example of covariant return type: interface Factory { function make(): object; } class UserFactory implements Factory { function make(): User; } And here is an example of contravariant parameter type: interface Concatable { function concat(Iterator $input); } class Collection implements Concatable { // accepts all iterables, not just Iterator function concat(iterable $input) {/* . . . */} } See the RFC for a closer look at covariance and contravariance in PHP 7.4. This RFC passed with 39 to 1 votes. PreloadingThis proposal from Dmitry Stogov is one of our favorite because it should bring a significant boost in performance. Preloading is the process of loading libraries and frameworks into the OPCache at module initialization (read more about PHP lifecycle). Here is how preloading works in the words of Dmitry:
These files are loaded on server startup, are executed before any application and stay available for any future requests. That’s great in terms of performance. Preloading is controlled by a specific php.ini directive: opcache.preload. This directive specifies a PHP script to be compiled and executed at server start-up. This file can be used to preload additional files, either including them or via the opcache_compile_file() function (read more on PHP documentation). But there’s a downside. In fact, the RFC explicitly states:
However, all functions defined in preloaded files will be permanently loaded into PHP function and class tables, and remain available for every future request. This will lead to good performance improvements, even if these improvements could be considerably variable. You can read more about the limitations and exceptions of preloading on the official Preloading RFC page. New Custom Object Serialization MechanismThis is another proposal from Nikita Popov approved with a large majority of votes. Currently, we have two different mechanisms for custom serialization of objects in PHP:
According to Nikita, both these options have issues that lead to complex and unreliable code. You can dive deep into this topic in the RFC. Here I just mention that the new serialization mechanism should prevent these issues by providing two new magic methods, __serialize() and __unserialize(), that combine the two existing mechanisms. This proposal passed with 20 to 7 votes. DeprecationsThe following functions/functionalities will be deprecated with PHP 7.4. For a more comprehensive list of deprecations, check out PHP 7.4 Upgrade Notes. Change the Precedence of the Concatenation OperatorCurrently, in PHP the “+” and “-” arithmetic operators, and the “.” string operator are left associative and have the same precedence (read more about Operator Precedence).As an example, consider the following line: echo "sum: " . $a + $b; In PHP 7.3 this code produces the following warning: Warning: A non-numeric value encountered in /app/types.php on line 4 This because the concatenation is evaluated from left to right. It’s the same as writing the following code: echo ("sum: " . $a) + $b; This RFC proposes to change the precedence of operators, giving “.” a lower precedence than “+” and “-” operators, so that additions and subtractions would always be performed before the string concatenation. That line of code should be equivalent to the following: echo "sum: " . ($a + $b); This is a two-step proposal:
Both proposals have been approved with a large majority of votes. Deprecate left-associative ternary operatorIn PHP the ternary operator, unlike many other languages, is left-associative. According to Nikita Popof, this can be confusing for programmers who switch between different languages. Currently, in PHP the following code is correct: $b = $a == 1 ? 'one' : $a == 2 ? 'two' : $a == 3 ? 'three' : 'other'; It’s interpreted as: $b = (($a == 1 ? 'one' : $a == 2) ? 'two' : $a == 3) ? 'three' : 'other'; And this could lead to errors because it may not be what we intend to do. So this RFC proposes to deprecate and remove the use of left-associativity for ternary operators and force developers to use parentheses. This is another two-step proposal:
This proposal has been approved with 35 to 10 votes. | |