📜 ⬆️ ⬇️

PHP 7.3. What's new


Syntax


  1. Mitigation of Heredoc and Nowdoc syntax
  2. Endpoint comma support in function and method calls
  3. Links to list()

Deprecated features


  1. The image2wbmp() function is deprecated.
  2. The FILTER_FLAG_SCHEME_REQUIRED and FILTER_FLAG_HOST_REQUIRED flags have FILTER_FLAG_SCHEME_REQUIRED FILTER_FLAG_HOST_REQUIRED when using FILTER_VALIDATE_URL
  3. Register-independent constants are deprecated.

New opportunities


  1. Optional throwing exceptions for errors in json_encode and json_decode
  2. Add is_countable() function
  3. Adding array_key_first() and array_key_last() functions

Changes


  1. Migrating from PCRE to PCRE2

Mitigation of Heredoc and Nowdoc syntax


Heredoc and Nowdoc required to put the closing identifier first in the new line.


Example:


 $foo = <<<IDENTIFIER the crazy dog jumps over the lazy fox "foo" bar; IDENTIFIER 

Here, the closing IDENTIFIER must be the first character on the new line for this to work. In addition, there should not have been any other characters after the closing identifier (except ; which is optional).


RFC for PHP 7.3 suggests removing such requirements to improve code readability. First of all, to add indents when using heredoc/nowdoc identifiers.


Full list of changes in heredoc/nowdoc syntax:


  1. The closing identifier does not have to be the first character in the string.
  2. The closing identifier is indented with spaces or tabs.
  3. Indenting (spaces or tabs) should not be mixed. If you do, you will get the Parse error: Invalid indentation - tabs and spaces cannot be mixed in .. on line ..
  4. The exact number of spaces / tabs used before the closing identifier will be removed from each line of the heredoc/nowdoc expression.
  5. If the number of backing characters used before the closing identifier is greater than in any of the lines of the expression, you will receive the Parse error: Invalid body indentation level (expecting an indentation level of at least ..) in .. on line ..
  6. several expressions after the closing identifier will work without errors

Here is a snippet that uses new features without breaking the new rules:


 $foo = ['foo', 'bar', <<<EOT baz - hello world! -- ahoy EOT, 'qux', 'quux' ]; var_dump($foo); 

The output will be:


 array(5) {        [0]=>           string(3) "foo" [1]=>           string(3) "bar" [2]=>           string(29) "baz - hello world! -- ahoy" [3]=> string(3) "qux" [4]=> string(4) "quux" }     ` 

Notice that the padding used in the declaration with heredoc not displayed in the var_dump() output, and we continued enumerating the elements of the array after the EOT identifier.


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


As long as you do not use a set of identical heredox/nowdoc character identifiers as the beginning of a line, you are on the line.


 $foo = <<<HELLO HELLO_WORLD <--         HELLOWORLD <--     HELLO WORLD <--    HELLO; 

If you have a heredoc/nowdoc syntax similar to the one described above, I note that with PHP 7.3, PHP will accept the first HELLO literal and will generate an error on the next line. In earlier versions, HELLO WORLD not perceived as a closing identifier for heredoc. Thanks / u / ImSuperObjective2 with reddit for pointing this out


Endpoint comma support in function and method calls


This is a simple change that permits the use of end commas in function calls and methods. This does not affect the declaration.


For example, the following syntax will be possible:


 //  foo('bar', 'baz',); //        'baz' 

In the pre-PHP-7.3 versions, the snippet above throws a PHP Parse error: syntax error, unexpected ')' in .. on line ..


You cannot use more than one comma at the end or use commas to skip arguments. This is mainly a change for a function with variable parameters. Also, with the new revisions, the syntax of the array will look more consistent.


Note that you cannot use this feature in function / method declarations; it is not right:


 function foo($bar, $baz, ) { // nah, you can't do this. } 

RFC , discussion on Externals.io , implementation


Impact on backward compatibility


No Existing code will continue to work. If you have function calls that accept variable parameters, add trailing commas to these places for convenience. But using them everywhere is obviously too much.


Links to list()


The list() function is useful for quickly assigning values ​​to temporary from an array. Before PHP 7.3, it was not possible to specify a variable by reference. Before PHP 7.3, the following snippet resulted in a fatal error:


 $arr = ['apple', 'orange']; list($a, &$b) = $arr; $b = 'banana'; echo $arr[1]; // Fatal error: [] and list() assignments cannot be by reference in .. on line .. 

One cannot refer to non-referencable variables: list($a, &$b) = [12, 14]; will give out a Fatal error: Cannot assign reference to non referencable value in .. on line ..


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


Not. Instead of using list() to populate several variables, I would suggest that you use value objects to make everything easier. They will still be passed by reference, but they will make your code much cleaner.


The image2wbmp() function is deprecated.


image2wbmp() function from the GD extension is used to display a WBMP (Wireless Bitmap) image. In PHP 7.3, it is deprecated in favor of the imagewbmp() function.


If you use image2wbmp() , then simply replace the function name with imagewbmp and everything will be fine! Over 5,500 image2wbmp() on github against more than 39,300 imagewbmp() . It seems that the PHP development team removes rarely used functions to minimize the impact.


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


If you use the image2wbmp() function, replace the call with imagewbmp . Take advantage of automation that can change this for you.


The FILTER_FLAG_SCHEME_REQUIRED and FILTER_FLAG_HOST_REQUIRED flags have FILTER_FLAG_SCHEME_REQUIRED FILTER_FLAG_HOST_REQUIRED when using FILTER_VALIDATE_URL


This is moving forward. When you use filter_var($var, FILTER_VALIDATE_URL) , there are two additional flags that can be set to ensure strict URL checking: FILTER_FLAG_SCHEME_REQUIRED and FILTER_FLAG_HOST_REQUIRED .
Since PHP 5.2.1, both of these flags are applied implicitly, regardless of whether they are set or not.


If your code uses these flags, just delete them and it will be fine. Currently there are over 5,000 search results on github using them.


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


Since both of these flags are deprecated, you will see a notification like:


 Deprecated: filter_var(): explicit use of FILTER_FLAG_SCHEME_REQUIRED and FILTER_FLAG_HOST_REQUIRED is deprecated in ... 

All you have to do is just remove two flags, because they are FILTER_VALIDATE_URL implied when using FILTER_VALIDATE_URL .


Register-independent constants are deprecated.


The define() function allows you to declare a constant in register-independent mode. You must explicitly declare a case-sensitive constant by passing in the third parameter of the function true . This is not the default behavior and is certainly not consistent with the ability to declare constants via the const keyword.


 define('Foo', 'Bar', true); 

The above code will throw out the expiration notice: Deprecated: define(): Declaration of case-insensitive constants is deprecated in ...


In addition, when you try to access constants that were declared in Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "Foo" ( FOO ) mode, you will see a rather useful warning: Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "Foo" Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "Foo"


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


You will have to go to the base code, where the case-insensitive constants are declared and consistently correct. It is highly unlikely that there will be no problems with this, because to catch all the use cases is quite labor-intensive, but as a result the code will become clearer.


I have not found examples of such use on github, but at least Drupal and WordPress (two fairly old and mature PHP projects) have case-independent constants.


Optional throwing exceptions for errors in json_encode and json_decode


One of my favorites. All these years, json_encode() and json_decode() silent about errors in PHP variables or json strings, which led to buggy code. This case was even in the famous criticism of PHP: Fractal of bad design .


json_decode returns null for invalid input, while null is an absolutely valid object for JSON to be decoded. This function is absolutely unreliable unless you call json_last_error every time you use it.

It took 6 years after that blog post and we had the opportunity to get an error about the json crashes:


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

The new \JsonException is a successor of \Exception , and the JSON_THROW_ON_ERROR constant and JsonException itself are in the global namespace.


I highly recommend that you start using this feature. There are third-party libraries, such as daverandom / exceptional-json , that implement similar functionality for versions of PHP 7.2 and below. With the advent of this function in the PHP core, you can remove this package and tons of ugly pattern code with json_last_error() in every place where you work with json.


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


None, unless you use your own exception and / or constant with the same names.


Add is_countable() function


PHP 7.2 has a lot of outdated and buggy functions. If you are in PHP 7.2. call count() using a non- countable variable, then PHP will display a warning about this. In general edits, there was a sentence to check the received variable on the countable before using it in count() .


countable variable is an array or an object that implements the \Countable interface. Since the test will use a lot of template code, PHP 7.3 introduced a new function is_countable() , which checks the variable for ... well ... possibility of use with count() .


I wrote a polyfill for is__countable () if you want to start using this feature right now.


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


Until its own is_countable() function is is_countable() , there will be no problems.


Adding array_key_first() and array_key_last() functions


In PHP, there are 75 different functions for working with arrays, but so far there has been no easy way to get the first and last keys of an array without changing the array pointer or iterating through all the keys (via array_keys() ) and then getting the first / last value.


There are two new functions, array_key_first() and array_key_last() that allow this.


The RFC also suggested adding array_value_first() and array_value_last() , but this part did not pass the vote.


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


If you have not declared your own array_key_first() and array_key_last() functions, then there will be no problems.


Migrating from PCRE to PCRE2


PHP uses Perl Compatible Regular Expressions or PCRE in the library for short work with regular expressions. With PHP 7.2, the 8.RE version of the PCRE legacy library is used, and in PHP 7.3 PCRE2 will already be used. Please note that PCRE2 is considered a new library, although it is largely compatible with PCRE (8.x).


A new library is more aggressive in pattern validation and can lead to errors in existing code. The following snippet will be invalid with PHP 7.3:


 preg_match('/[\w-.]+/', ''); 

PHP will throw a warning Warning: preg_match(): Compilation failed: invalid range in character class at offset 3 .
The problem with the template: for this to work the hyphen must be moved to the end or shielded.


 preg_match('/[\w\-.]+/', ''); 

The above code will work fine not only with PHP 7.3, but also with older versions. In the new pattern the hyphen is screened - in \- . This is the most common problem of all that can be encountered when deciding on compatibility issues.


This is a fairly minor change, but there is a chance that things will go wrong. The error message indicates the exact position of the character in the regular expression. Be sure to check your code carefully. Check your regular expressions for compatibility with PCRE2 syntax via Regex Buddy or other similar software. For more information, see the description of PCRE2 syntax and obsolete PCRE syntax .


RFC , discussion on Externals.io , implementation


Impact on backward compatibility


Since PCRE2 is more picky and strict with templates, some of your preg_match() and similar calls may not work. The fix ranges from a simple template update (for example, screening hyphens) to rewriting templates. Make sure all your tests pass.


')

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


All Articles