What is new in PHP 7.1?

On December 1, 2016 the PHP development team released the PHP 7.1 version, 12 news features was added, here we covered 8 of them:

1. Nullable types

In the PHP 7.0 version function declaration accepts a return type, with the release of 7.1 version functions and parameters can return/accept null by prefixing the data type with a question mark(?).

if the data type passed as parameter or returned by a function is different from the type specified a TypeError exception will be thrown.

Examples

1. Nullable return type

<?php
function returnStringOrNull($valueToReturn): ?string {
    return $valueToReturn;
}

echo 'LibreByte:', gettype(returnStringOrNull('LibreByte')), nl2br("\n");
echo 'null:', gettype(returnStringOrNull(null)), nl2br("\n");
echo '25:', gettype(returnStringOrNull(25)), nl2br("\n");
echo 'SdtClass object:', gettype(returnStringOrNull(new StdClass())), nl2br("\n");

// Print
// LibreByte:string
// null:NULL
// 25:string
// SdtClass object:
// Fatal error: Uncaught TypeError: Return value of returnStringOrNull() must be of the type string or null, object returned...

2. Nullable parameter type

<?php
function stringOrNullParam(?string $param) {
    echo 'Param: ', is_null($param) ? "'null'" : "'$param'", ", type: ", gettype($param), nl2br("\n");
}

stringOrNullParam('LibreByte');
stringOrNullParam(null);
stringOrNullParam(25);
stringOrNullParam(new StdClass());

// Print
// Param: 'LibreByte', type: string
// Param: 'null', type: NULL
// Param: '25', type: string
// Fatal error: Uncaught TypeError: Argument 1 passed to stringOrNullParam() must be of the type string or null, object given...

2. Void functions

The void functions should not return any value therefore they should use an empty return or ignore it completely, I think if the return is ignored it gives more clarity to the code since it is more compatible void definition, the NULL value is not a valid return value for void functions.

<?php
a = 10;

function voidWithoutReturn(&$param, $newValue): void {
    $param = $newValue;
}

function voidWithEmptyReturn(&$param, $newValue): void {
    $param = $newValue;
    return;
}

echo 'Initial value for a: ', $a, nl2br("\n");
voidWithoutReturn($a, 25);
echo 'Called voidWithoutReturn($a, 25), $a = ', $a, nl2br("\n");
voidWithEmptyReturn($a, 30);
echo 'Called voidWithEmptyReturn($a, 30), a = ', $a, nl2br("\n");

// Print
// Initial value for a: 10
// Called voidWithoutReturn($a, 25), $a = 25
// Called voidWithEmptyReturn($a, 30), a = 30

if you return a value inside a void function the PHP engine will emit an error like this:

Fatal error: A void function must not return a value...

3. Symmetric array destructuring

The shorthand array syntax ([]) may now be used to destructure arrays for assignments (including within foreach), as an alternative to the existing list() syntax, which is still supported.

<?php
$playerRank = [
    ['Carlsen',    'Norway',     2842],
    ['Caruana',    'USA',        2822],
    ['Mamedyarov', 'Azerbaijan', 2801],
    ['Ding Liren', 'China',      2797],
    ['Kramnik',    'Russia',     2790],
];

[$player1, $player2] = $playerRank;

echo "<strong>Player 1 is:</strong>", nl2br("\n");

foreach ($player1 as $data) {
    echo $data, nl2br("\n");
}
// Print
// Player 1 is:
// Carlsen
// Norway
// 2842

echo  nl2br("\n");
echo "<strong>Player 2 is:</strong>", nl2br("\n");

foreach ($player2 as $data) {
    echo $data, nl2br("\n");
}
// Print
// Player 2 is:
// Caruana
// USA
// 2822
echo  nl2br("\n");
echo "<strong>Player List:</strong>", nl2br("\n");

foreach ($playerRank as [$name, $country, $elo]) {
    echo "<strong>Player Name:</strong> $name, ", "<strong>Player Country: </strong> $country,",  "<strong>Elo: </strong> $elo";
    echo  nl2br("\n");
}
// Print
// Player List:
// Player Name: Carlsen, Player Country: Norway,Elo: 2842
// Player Name: Caruana, Player Country: USA,Elo: 2822
// Player Name: Mamedyarov, Player Country: Azerbaijan,Elo: 2801
// Player Name: Ding Liren, Player Country: China,Elo: 2797
// Player Name: Kramnik, Player Country: Russia,Elo: 2790

It is also possible to use indexes.

<?php
echo "<strong>Countries:</strong>", nl2br("\n");

$countries = [
    'SPAIN'   => ['EUR', 'ES'],
    'USA'     => ['USD', 'EN'],
    'ECUADOR' => ['USD', 'ES'],
    'CUBA'    => ['CUC', 'ES'],
    'FRANCE'  => ['EUR', 'FR']
];

foreach ($countries as $countryName => [$currency, $lang]) {
    echo "<strong>Country: </strong> $countryName, <strong>Currency: </strong> $currency, <strong>Language: </strong> $lang";
    echo  nl2br("\n");
}
// Print
// Countries:
// Country: SPAIN, Currency: EUR, Language: ES
// Country: USA, Currency: USD, Language: EN
// Country: ECUADOR, Currency: USD, Language: ES
// Country: CUBA, Currency: CUC, Language: ES
// Country: FRANCE, Currency: EUR, Language: FR

4. Class constant visibility

This feature improves Object-Oriented Programming encapsulation in Object-Oriented Programming due the visibility or scope of class constants can be defined:

  • public: by default, visible from anywhere in your application
  • protected: visible in the class where it is declared and subclasses
  • private: only visible in the class where it is declared.
<?php
class Blog
{
    const BLOG_NAME = 'LibreByte';
    protected const START_DATE = '01-01-2007';
    private const CREATOR = 'srd0tlibr3';
}

class Page extends Blog
{
    public static function printDetails()
    {
        echo "Blog name: ", self::BLOG_NAME, nl2br("\n");
        echo "Blog start date: ", self::START_DATE, nl2br("\n");
        echo "Blog creator: ", self::CREATOR, nl2br("\n");
    }
}

Page::printDetails();

// Print
// Blog name: LibreByte
// Blog start date: 01-01-2007
// Blog creator: 
// Fatal error: Uncaught Error: Undefined class constant 'CREATOR'

Note that CREATOR constant is not visible from Page class

5. iterable pseudo-type

A new pseudo-type (similar to callable) called iterable has been introduced. It may be used in parameter and return types, where it accepts either arrays or objects that implement the Traversable interface. With respect to subtyping, parameter types of child classes may broaden a parent’s declaration of array or Traversable to iterable. With return types, child classes may narrow a parent’s return type of iterable to array or an object that implements Traversable.

<?php
function xrange($start, $limit, $step = 1) {
    for ($i = $start; $i <= $limit; $i += $step) {
        yield $i;
    }
}

function iterate(iterable $iter)
{
    foreach ($iter as $val) {
        echo $val, ' ';
    }
}
// Print: 1 2 3 4 5 6 7 8 9 10
iterate(xrange(1, 10));

Note the above is possible because the Generator class implements the Iterator interface.

6. Multi catch exception handling

Multiple exceptions per catch block may now be specified using the pipe character (|). This is useful for when different exceptions from different class hierarchies are handled the same.

<?php
function validateAge($age)
{
    if (!is_int($age)) {
        throw new InvalidArgumentException('Age must be integer!');
    }

    if (($age < 0) || ($age > 200)) {
        throw new DomainException('Age must be a value between 0 and 200!');
    }

    return true;
}

foreach ([3.5, 250] as $age) {
    try {
        if (validateAge($age)) {
            echo 'Valid age!', nl2br("\n");
        }
    } catch (InvalidArgumentException|DomainException $e) {
        echo $e->getMessage(), nl2br("\n");
    }
}

// Print
// Age must be integer!
// Age must be a value between 0 and 200!

7. Support for keys in list()

You can now specify keys in list(), or its new shorthand [] syntax. This enables destructuring of arrays with non-integer or non-sequential keys.

<?php

$countries = [
    ['country' => 'Spain', 'lang' => 'ES', 'currency' => 'EUR'],
    ['country' => 'USA', 'lang' => 'EN', 'currency' => 'USD']
];

foreach ($countries as ['country' => $countryName, 'lang' => $language, 'currency' => $currency]) {
    echo "<strong>Country: </strong> $countryName, <strong>Language: </strong> $language, <strong>Currency: </strong> $currency";
    echo  nl2br("\n");
}

// Print
// Country: Spain, Language: ES, Currency: EUR
// Country: USA, Language: EN, Currency: USD

8. Support for negative string offsets

Support for negative string offsets has been added to the string manipulation functions accepting offsets, as well as to string indexing with [] or {}. In such cases, a negative offset is interpreted as being an offset from the end of the string.

<?php
var_dump("abcdef"[-2]); // Print: string (1) "e"
var_dump(strpos("aabbcc", "b", -3)); // Print: int(3)
$string = 'bar';
echo "The last character of '$string' is '$string[-1]'.\n";
// Print: The last character of 'bar' is 'r'. 

Further readings

YouTube video

PHP new features, 2 (8)

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.