More upcoming features in PHP 7.1 : speed is impressive again

More upcoming features in PHP 7.1

More upcoming features in PHP 7.1

This is the second part of our series about last features in PHP 7.1. See ‘Upcoming features in PHP 7.1 (part a)‘ and ‘More upcoming features in PHP 7.1 (part b)‘ and ‘last features in PHP 7.1 (part c)

PHP 7.1 is already Beta 3 as we’re writing, and should be released somewhere by November 2016 (or close). We are now presenting another batch of new features that PHP 7.1 simply piles on top of PHP 7.0.

 

Nullable types

Last week, we introduced the new Void return type: methods that don’t return anything may use this as return type. But what is the function may return NULL or something else, just like good old strpos()? This is the new nullable types feature.

Type hints, both return and arguments, get a new option that allow then to be null, or the mentioned type. This works like this:

<?php
function foo(): ?int  {
    return null; //ok
    return 3;    //ok
    return "3";  //not ok, sometimes
    return "ko"; //never OK, as it can't be cast to a integer
}
 
function bar(?string $msg = “default”) {
    if ($msg!== null) {
        echo $msg;
    }
}

bar("ok") ;       // OK
bar(null) ;       // OK, displays nothing
bar(4) ;          // OK, if the script is not in strict mode

bar() ;           // OK, display 'default' 
?>

One interesting piece of detail is the relation between nullable type and default values. A type may have both. Default value will apply when NO argument is given: if an argument is given, but is null, then it is accepted, and then passed as is. This is illustrated in the example above. Of course, there are no default values for return type.

You may learn more about this new feature from the RFC: https://wiki.php.net/rfc/nullable_types

Iterable type

While we’re finishing the Type hint section, there is a new keyword for PHP: iterable. It represents any structure that may be given to a foreach loop or a yield from operator, such as array (the simple type), the class object, generators or any Traversable classes. It may be used as type hint, or return type.

This is not a real type : it covers several distinct classes or type of data, that can’t be grouped under a single type hint. Like int, void or callable, it is now forbidden to use it as class, trait or interface name, although no such class exists.

<?php
function bar(): iterable {
    return [1, 2, 3];
}
?>

Related to this feature, a function named is_iterable() was also introduced, to check variable for this typehint. Read more about iterable in https://wiki.php.net/rfc/iterable.

Class constant visibility

Up to PHP 7.1, class constant were always public: there was no way to hide them inside a class, and they would be accessible to every other part of the code. Starting with PHP 7.1, it is now possible to restrict the usage of class constant, with private, protected or public, the latter one being the default behavior for backward compatibility.

<?php
class Foo {
	// PHP 7.0 behavior. Nothing changes.
        const PUBLIC_CONST = 0;
 
        // Explicit visibilities
        private const PRIVATE_CONST = 1;
        protected const PROTECTED_CONST = 2;
        public const PUBLIC_CONST_TWO = 3, PUBLIC_CONST_THREE = 4;
}
?>

Interfaces may only have public constants, and triggers a compile time error when it is not the case. Non-class constant cannot have visibility too. Trait cannot have constants, so they are not involved.

Octal sequence fixes

Octal numbers got their fix in PHP 7.0, where they are now validated at compile time: the invalid octals generate a compile time error. In PHP 7.1, it is now time for string octal sequences. Octal sequences are string sequences, where a character is represented by its octal notation:

<?php

print "\123\n"; // Prints S

print "\523\n"; // Prints S too

?>

PHP 7.0 and earlier didn’t validate the octal value (here 123 and 523) and silently turned it into a character, modulo 400. This is now a syntax error, for anything that is beyond \377:

Octal escape sequence overflow \523 is greater than \377

If you’re concerned by this error, PHP 7.1 lint your code before migration.

Warn about invalid string in arithmetics

PHP usually takes care of type juggling for us, and converts auto-magically any number in a string like ‘1’ or ‘-1.2’ to its numeric equivalent, when it is used in math context. Thus, ‘1’ + 3 === 4. So far, this doesn’t change in PHP 7.1.

On the other hand, what does change is that PHP will now emit a warning whenever the string to numeric conversion meets a problem. So, ‘1 elephpant’ + 3 === 4 is still OK, but will also generate Notice: A non well formed numeric string encountered.

The notice will be edited if the string can’t be turned into a number, which happens when the string contains non-numeric characters (« 12.00 $CAD »), non-USA conventions (« 1 023,45 ») or even white spaces («  234  »). This apply to literals, thought it won’t be checked at compile time ; most importantly, it applies to any values at run time, including any filter by addition :

<?php
$amount = abs($_GET['amount']) + 0 ; // Make this a safe integer.
?>

A special case that may lead to back-ward incompatibility is scientific notation. The magical conversion that took place used to be handled by 3 different functioncalls, all behaving differently with scientific notation. Thus,

<?php
echo "1.2345e9" + 0;
echo (int) "1.2345e9";
?>

PHP 7.0 processes both expression in different ways : the first line is 123450 while the second is 1 (since dot ‘.’ is not a valid integer character). In PHP 7.1, behavior are all the same, and scientific notation is always recognized. This may lead to some backward incompatibilities, when the beginning of the string may be mistaken with a scientific number.

Expect to hear a lot from this feature.

New functions

We already have seen is_iterable(), which was introduced with the type hint iterable. Here are the new functions :

  • mb_ord() and mb_chr() are better version of mb_encode() and decode_numericentity(), and multi-byte version for ord()/chr(). They also take an encoding as second parameter, or use mbstring.internal_encoding as default one.

$char_code = mb_chr($mb_char [, $encoding = mbstring.internal_encoding] )
$mb_char = mb_ord($char_code [, $encoding = mbstring.internal_encoding] )

  • mb_scrub() cleans the string provided as first argument, for the encoding provided as second argument, and using the substitutions provided as third arguments.
  • curl_share_strerror(), curl_multi_errno() and curl_share_errno() all provide access to errors happening during a curl session, and ways to get a human readable message.
  • sapi_windows_cp_set(), sapi_windows_cp_get(), sapi_windows_cp_is_utf8(),sapi_windows_cp_conv() have been added for codepage handling.

More next week (again!)

That is be enough for a second part, and there is even some left for dessert. We’ll be back next week with more on PHP 7.1, with Closure::fromCallable, changed functions, random numbers, and call_user_func()

Tweet about this on TwitterShare on RedditShare on LinkedInEmail this to someone