PHP 7.3. What's new

Original author: Ayesh Karunaratne
  • Transfer


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

Deprecated features

  1. Feature image2wbmp()deprecated
  3. Register-independent constants are deprecated.

New opportunities

  1. Optional throw exception for errors in functions json_encodeandjson_decode
  2. Add function is_countable()
  3. Add features array_key_first()andarray_key_last()


  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.


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

Here, the closing IDENTIFIERmust 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/nowdocidentifiers.

Full list of heredoc/nowdocsyntax changes :

  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 it 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/nowdocexpression.
  5. If the number of backing characters used before the closing identifier is greater than in any of the expression lines, you will get 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  
   -  hello world! --  
  EOT, 'qux', 'quux'  

The output will be:

array(5) {          
  string(3) "foo"   
  string(3) "bar"   
  string(29) "baz   
  -  hello world! --  
  string(3) "qux"  
  string(4) "quux"  
}     `

Notice that the padding used in the declaration with the help is heredocnot displayed in the output var_dump(), and we continued to list the elements of the array after the EOTidentifier.

RFC , discussion on , implementation

Impact on backward compatibility

As long as you do not use a set of identical heredox/nowdocidentifiers of characters as the beginning of a line, you are at stake.

$foo = <<<HELLO  
  HELLO_WORLD <-- это не будет приниматься за окончание строкового литерала
  HELLOWORLD  <-- и это не будет
  HELLO WORLD <-- а это будет 

If you have a heredoc/nowdocsyntax similar to the above, I note that with PHP 7.3, PHP will accept the first HELLOliteral and will generate an error on the next line. In earlier versions it was HELLO WORLDnot perceived as a closing identifier for heredoc. Thanks / u / ImSuperObjective2 with reddit for pointing this out

Endpoint comma support in function calls and methods

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 an error 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. Basically, this is 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:

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

RFC , discussion on , 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 to use them everywhere is obviously too much.

Links to list()

The function list()is useful for quickly assigning values ​​to temporary from the 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 ..

It is impossible to refer to non-referencablevariables: list($a, &$b) = [12, 14];will issue Fatal error: Cannot assign reference to non referencable value in .. on line ...

RFC , discussion on , implementation

Impact on backward compatibility

Not. Instead of using list()multiple variables to fill in, 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.

Feature image2wbmp()deprecated

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

If you are using image2wbmp(), then simply replace the function name with imagewbmpand everything will be fine! More 5,500 упоминаний image2wbmp()on github against more 39,300 упоминаний imagewbmp(). It seems that the PHP development team removes rarely used functions to minimize the impact.

RFC , discussion on , implementation

Impact on backward compatibility

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


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 verification of the URL: FILTER_FLAG_SCHEME_REQUIREDand 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 , 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 isdeprecatedin ...

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

Register-independent constants are deprecated.

The function define()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 a keyword const.

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

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

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

RFC , discussion on , 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 catching 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 throw exception for errors in functions json_encodeandjson_decode

One of my favorites. All these years json_encode()they were 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_decodereturns null for invalid input, while null is an absolutely valid object for the JSON being decoded. This function is absolutely unreliable, unless of course you call it json_last_errorevery 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 one \JsonExceptionis an heir of \Exception, and the constant JSON_THROW_ON_ERRORitself JsonExceptionis 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 sample code with a call json_last_error()in every place where you work with json.

RFC , discussion on , implementation

Impact on backward compatibility

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

Add function is_countable()

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

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

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

RFC , discussion on , implementation

Impact on backward compatibility

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

Add features array_key_first()andarray_key_last()

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 over all keys (through array_keys()) and then getting the first / last value.

There are two new features, array_key_first()and array_key_last()allowing it to do.

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

RFC , discussion on , implementation

Impact on backward compatibility

If you did not declare your own array_key_first()and array_key_last()functions, then problems will not arise.

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

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

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

PHP will throw out 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 Buddyor another similar software. For more information, see the description of PCRE2 syntax and obsolete PCRE syntax .

RFC , discussion on , implementation

Impact on backward compatibility

Since PCRE2 is more picky and strict about patterns, 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.

Also popular now: