Nouveautés PHP 7.1

+ rappels PHP 7.0

Appuyez sur [s] pour ouvrir les notes présentateur dans une nouvelle fenêtre.

Utilisez la touche [ESPACE]
pour passer au slide suivant.

PHP 5.x + 1

On en est où ?

  • PHP 5.6
    • Dernière version 5.x
    • Publiée le 28 août 2014
  • PHP 7.0
    • Publiée le 3 décembre 2015
  • PHP 7.1
    • Feature freeze
    • Publication : fin 2016 ?

Versions supportées

Supported Versions

php.net/supported-versions.php

PHP 7.0

Null Coalesce Operator


$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
                        

$username = $_GET['user'] ?? 'nobody';
                        

$model = Model::get($id) ?? $default_model;
                        

function foo() {
    echo "executed!", PHP_EOL;
}
var_dump(true ?? foo());
                        

Unicode Codepoint Escape Syntax


$ php -r 'echo "I \u{2665} PHP!\n";'
I ♥ PHP!
                        

$ php -r 'echo "\u{1F408} \u{1F431} \u{1F638} \u{1F639} \u{1F63A} \u{1F63B} \u{1F63C} \u{1F63D} \u{1F63E} \u{1F63F} \u{1F640} - so cute!!!\n";'
🐈 🐱 😸 😹 😺 😻 😼 😽 😾 😿 🙀 - so cute!!!
                        

wiki.php.net/rfc/unicode_escape

Type hints scalaires


function add(int $a, int $b) {
    return $a + $b;
}
                        

var_dump( add(10, 20) );
var_dump( add('10', '20') );
                        

int(30)
int(30)
                        

Type hints scalaires


try {
    var_dump( add(10, 'abc') );
}
catch (TypeError $e) {
    var_dump( $e->getMessage() );
}
                        

string(148) "Argument 2 passed to add()
    must be of the type integer, string given,
    called in .../test-01.php on line 12"
                        

Types de retour


function add(int $a, int $b) : int {
    return $a + $b;
}
                        

Types de retour


function get_config() : array {
    return 42;
}
get_config();
                        

Fatal error: Uncaught TypeError:
    Return value of get_config() must be
    of the type array, integer returned
                        

Typage strict


declare(strict_types=1);

function add(int $a, int $b) {
    return $a + $b;
}

add(10, '20');
                        

Fatal error: Uncaught TypeError:
    Argument 2 passed to add()
    must be of the type integer, string given
                        

Souple / Strict ?

  • Paramètres : au choix de l'appelant
    • Sait si il manipule des types souples ou stricts
  • Retour : au choix de l'appelé
    • Sait si la fonction qu'il a écrite utilise des types souples ou stricts

Souple / Strict ?

  • Les données sont des types indiqués.
  • Détermine si des conversions sont ou non permises.

Combined Comparison (Spaceship) Operator


function order_func($a, $b) {
    return $a <=> $b;
}
                        

function order_func($a, $b) {
    return [$a->x, $a->y, $a->foo]
        <=> [$b->x, $b->y, $b->foo];
}
                        

wiki.php.net/rfc/combined-comparison-operator

Group use declarations


use Mon\Espace\De\Nom\ClasseAa;
use Mon\Espace\De\Nom\ClasseBb;
use Mon\Espace\De\Nom\ClasseCc;
use Mon\Espace\De\Nom\Enfant\AutreClasse as ClassDd;
                        

use Mon\Espace\De\Nom\ {
    ClasseAa, ClasseBb, ClasseCc,
    Enfant\AutreClasse as ClassDd
};
                        

Group use declarations


use function Mon\Nom\fonc01;
use const Mon\Nom\CONST01;
use Mon\Nom\Class01;
                        

use Mon\Nom\ {
    function fonc01,
    const CONST01,
    Class01
};
                        

Erreurs → exceptions

  • Une partie des erreurs Fatales
  • internes à / levées par PHP
  • sont transformées en Error
  • qui peuvent être catchées

Erreurs → exceptions


$obj = null;
try {
    // Ooops !
    $obj->methode();
}
catch (Error $e) {
    var_dump($e>getMessage());
}
                        

string(43) "Call to a member function methode() on null"
                        

Erreurs → exceptions


$php = <<<'PHP'
$a = 10        // -- Parse error ! -- //
printf("\$a = %d\n", $a);
PHP;

try {
    eval($php);
}
catch (ParseError $e) {
    var_dump($e->getMessage());
}
                        

string(44) "syntax error, unexpected 'printf' (T_STRING)"
                        

Erreurs → exceptions


echo "Fichier 1 - avant\n";
try {
    // Fichier avec une erreur de syntaxe
    include __DIR__ . '/test-06-2.php';
}
catch (Error $e) {
    echo "Error catchée : ";
    var_dump($e->getMessage());
}
echo "Fichier 1 - après\n";
                        

Fichier 1 - avant
Error catchée : string(42) "syntax error, unexpected '$b' (T_VARIABLE)"
Fichier 1 - après
                        

Erreurs → exceptions

Hiérarchie d'erreurs / exceptions


interface Throwable
    Exception implements Throwable
        // Toutes les exceptions usuelles
    Error implements Throwable
        AssertionError extends Error
        ParseError extends Error
        TypeError extends Error
                        

Erreurs → exceptions

  • Une partie des erreurs Fatales
  • internes à / levées par PHP

Classes anonymes


$obj = new class ("Monde") {
    protected $qui;

    public function __construct($qui) {
        $this->qui = $qui;
    }

    public function hello() {
        printf("Hello, %s !\n", $this->qui);
    }
};

var_dump($obj);
$obj->hello();
                        

Classes anonymes


object(class@anonymous)#1 (1) {
  ["qui":protected]=>
  string(5) "Monde"
}
Hello, Monde !
                        

Generators et return


function plop() {
    yield 100;
    yield 200;
    return 42;
}

foreach (($generator = plop()) as $val) {
    var_dump($val);
}

var_dump( $generator->getReturn() );
                        

int(100)
int(200)
int(42)
                        

Generator Delegation


function test() {
    yield from [10, 20, 30];
}

foreach (test() as $val) {
    var_dump($val);
}
                        

int(10)
int(20)
int(30)
                        

Generator Delegation


function sub_generator_1() {
    yield 10;
    yield 20;
}
function sub_generator_2() {
    yield from [ 'aa', 'bb', ];
}
function delegating_generator() {
    yield from sub_generator_1();
    yield from sub_generator_2();
}

foreach (delegating_generator() as $val) {
    var_dump($val);
}
                    

int(10)
int(20)
string(2) "aa"
string(2) "bb"
                        

PHP 7.1

Class Constant Visibility


class MaClasse {
    public const MA_PUBLIQUE = 42;
    private const MA_PRIVEE = 1234;
    public function test() {
        var_dump( self::MA_PRIVEE );
    }
}
                        

var_dump( MaClasse::MA_PUBLIQUE ); // int(42)
(new MaClasse())->test(); // int(1234)
                        

// Error: Cannot access private const MaClasse::MA_PRIVEE
var_dump( MaClasse::MA_PRIVEE );
                        

wiki.php.net/rfc/class_const_visibility

Allow specifying keys in list()


$array = [
    'glop' => "Hello",
    'plop' => 123456,
    'who' => "World",
];
                        

list (
    'glop' => $a,
    'who' => $b
) = $array;
                        

var_dump($a, $b);
// string(5) "Hello"
// string(5) "World"
                        

wiki.php.net/rfc/list_keys

Generalize support of negative string offsets


$str = "Pascal";
var_dump($str[2]);  // string(1) "s"
var_dump($str[-2]); // string(1) "a"
                        

PHP 7.0 :


string(1) "s"
string(0) ""
                            

wiki.php.net/rfc/negative-string-offsets

Generalize support of negative string offsets


$str = "Pas.al";
$str[-3] = 'c';
var_dump($str);  // string(6) "Pascal"
                        

PHP 7.0 :


Warning: Illegal string offset:  -3
                            

wiki.php.net/rfc/negative-string-offsets

Generalize support of negative string offsets


var_dump( strpos("Pascal", "c", -5) ); // int(3)
                        

PHP 7.0 :


Warning: strpos(): Offset not contained in string
                            

wiki.php.net/rfc/negative-string-offsets

Catching Multiple Exception Types


class Plop extends Exception {}
class Blah extends Exception {}
class Another extends Exception {}
                        

try {
    switch (mt_rand(0, 2)) {
        case 0: throw new Plop();
        case 1: throw new Blah();
        case 2: throw new Another();
    }
} catch (Plop | Blah $e) {
    printf("1er catch : %s\n", get_class($e));
} catch (Another $e) {
    printf("2nd catch : %s\n", get_class($e));
}
                        

wiki.php.net/rfc/multiple-catch

Square bracket syntax for array destructuring assignment


[$a, $b] = [10, 20];
var_dump($a, $b);
// int(10)
// int(20)
                        

['glop' => $glop, 'plop' => $plop] = [
    'plop' => 42,
    'glop' => "Hello",
];
var_dump($plop, $glop);
// int(42)
// string(5) "Hello"
                        

wiki.php.net/rfc/short_list_syntax

Nullable Types


function fonc01(?int $a) {
    var_dump($a);
}
                        

fonc01(100); // int(100)
fonc01(null); // NULL
                        

fonc01();
// Error: Too few arguments to function fonc01(), 0 passed
                        

wiki.php.net/rfc/nullable_types

Nullable Types

PHP 7.0


function fonc01(int $a) {
    var_dump($a);
}
                        

fonc01(100); // int(100)
fonc01(null); // TypeError: Argument 1 passed to
              // fonc01() must be of the type
              // integer, null given
                        

wiki.php.net/rfc/nullable_types

Nullable Types


function fonc02(?int $a, ?int $b) : ?int {
    if ($a === null || $b === null) {
        return null;
    }
    return $a + $b;
}
                        

var_dump( fonc02(10, 20) ); // int(30)
var_dump( fonc02(10, null) ); // NULL
                        

wiki.php.net/rfc/nullable_types

Nullable Types

PHP 7.0


function fonc02(int $a, $b) : int {
    if ($a === null || $b === null) {
        return null;
    }
    return $a + $b;
}
                        

var_dump( fonc02(10, 20) ); // int(30)
var_dump( fonc02(10, null) ); // TypeError:
    // Return value of fonc02() must be of
    // the type integer, null returned
                        

wiki.php.net/rfc/nullable_types

Void Return Type


function fonc01() {
    printf("%s\n", __FUNCTION__);
}
                        

function fonc02() : void {
    printf("%s\n", __FUNCTION__);
}
                        

function function03() : void {
    printf("%s\n", __FUNCTION__);

    // Fatal error: A void function must not return a value
    return 'plop';
}
                        

wiki.php.net/rfc/void_return_type

Closure from callable function


function ma_fonction() {
    var_dump(__FUNCTION__);
}
                        

$closure = Closure::fromCallable('ma_fonction');
$closure();  // string(11) "ma_fonction"
                        

$closure = Closure::fromCallable('plop');
// TypeError: Failed to create closure from callable:
// function 'plop' not found or invalid function name
                        

wiki.php.net/rfc/closurefromcallable

Iterable


function fonc01(iterable $data) {
    foreach ($data as $key => $val) {
        // ...
    }
}
                        

fonc01([10, 20, 30]);
fonc01(new SplFixedArray(5));
fonc01(mon_generateur());
                        

fonc01("plop");
// TypeError: Argument 1 passed to fonc01()
// must be iterable, string given
                        

wiki.php.net/rfc/iterable

Throw Error in Extensions

La majorité des erreurs fatales levées par des extensions intégrées à PHP sont converties en exceptions.

wiki.php.net/rfc/throw_error_in_extensions

Asynchronous Signal Handling

Sans declare(ticks=1)


pcntl_async_signals(true);

pcntl_signal(SIGTERM, function ($signo) {
    var_dump("SIGTERM"); die;
});

while (true) {
    usleep(100);
}
                        

wiki.php.net/rfc/async_signals

En route vers PHP 8.0 ?

Futures suppressions

  • Deprecate mb_ereg_replace() eval option — RFC
  • Deprecate (then Remove) Mcrypt — RFC

Et donc ?