PHP 7.1 : des améliorations de syntaxe, un langage plus cohérent

12 septembre 2016php, php-7.1
 Cet article a été rédigé il y a plusieurs années et peut ne plus être tout à fait à jour…

This post is also available in English.
Ceci est le sixième article d’une série à propos de PHP 7.1.


Une nouvelle version de PHP, c’est aussi l’occasion d’améliorer certains points de syntaxe, ou d’apporter quelques évolutions mineures au langage. Voici quelques-uns des points qui ont le plus attiré mon regard, pour PHP 7.1.

Allow specifying keys in list()

La première de ces évolutions porte sur le mot-clé list et sur l’extraction de données depuis un tableau : list() accepte désormais les clés des éléments à extraire.

Par exemple, pour n’extraire que les éléments de clés 'glop' et 'who' d’un tableau de trois éléments, nous pouvons désormais utiliser l’écriture suivante :

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

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

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

Cette approche est plus sure et plus lisible que celle où nous nous basions uniquement sur la position des différents éléments du tableau.

‣ La RFC : Allow specifying keys in list()


Square bracket syntax for array destructuring assignment

Nous pouvons depuis PHP 5.4 utiliser une syntaxe courte pour construire des tableaux : [10, 20, 30]. À partir de PHP 7.1, nous allons pouvoir utiliser cette même syntaxe courte pour la déconstruction de tableaux, sans avoir à employer le mot-clé list :

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

Il est à noter que cette syntaxe est bien sûr compatible avec le point vu juste au-dessus :

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

Pas une révolution, mais plus de cohérence dans le langage !

‣ La RFC : Square bracket syntax for array destructuring assignment


Generalize support of negative string offsets

Encore une petite évolution, qui rend PHP plus cohérent avec lui-même et avec d’autres langages, et qui va dans certains cas bien nous simplifier les choses : le support pour les indexes négatifs lors de manipulations de chaines de caractères a été généralisé.

Cela signifie qu’on peut désormais utiliser un index négatif pour accéder à un caractère d’une chaine, en partant de la fin de celle-ci :

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

Pour rappel, avec PHP 7.0, la seconde écriture aurait retourné une chaine vide.

Cette syntaxe fonctionne également en affectation pour modifier un caractère précis, là où PHP 7.0 aurait levé un avertissement :

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

Plusieurs fonctions de manipulation de chaines ont également été enrichies, de manière à accepter de compter à partir de la fin de la chaine. Par exemple :

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

Là aussi, PHP 7.0 levait un avertissement.

‣ La RFC, qui liste toutes les fonctions modifiées : Generalize support of negative string offsets


Class Constant Visibility

Il m’arrive parfois – et je vois fréquemment le cas en revues de code – d’avoir besoin de définir une constante interne à une classe.

Pour cela, avec PHP 7.0, deux possibilités :

  • Définir une constante de classe avec const : on a l’avantage d’avoir une constante qui ne peut changer de valeur, mais elle est nécessairement publique.
  • Ou définir une variable statique privée avec private static : on a l’avantage d’avoir une donnée privée qui ne sera pas utilisée depuis l’extérieur de la classe (elle ne fait pas partie de son API), mais il s’agit d’une variable et pas d’une constante.

PHP 7.1 répond à cette problématique, en permettant de spécifier une visibilité sur les constantes de classes :

class MaClasse {
    public const MA_PUBLIQUE = 42;
    private const MA_PRIVEE = 1234;

    public function test() {
        var_dump( self::MA_PRIVEE );
    }
}

Fort logiquement, les trois mots-clés public, protected et private reprennent le sens qu’ils avaient déjà pour les attributs et méthodes :

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

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

Voici une évolution qui pourrait sembler mineure au premier abord, mais je sais déjà que je vais l’utiliser ;-)

‣ La RFC : Support Class Constant Visibility