Faut-il passer à PHP 7 (en fait 7.1) ? La question devient pertinente pour les utilisateurs de Laravel parce que la version 5.5 de ce framework imposera cette version de PHP. Alors je vous propose de faire un peu le point de ce que nous apporte ce nouveau PHP…

Déjà on va y gagner en performances puisqu’on nous annonce un gain en 25% et 70%. Bon la marge est grande !

Mais au niveau des fonctionnalités ? Vous pouvez tout trouver dans le manuel.

Pour les allergiques à l’anglais voyons un peu ça en me limitant à ce qui me semble le plus important…

Groupement des « use »

L’utilisation des espaces de noms nous amène à effectuer de nombreuse déclarations. On va pouvoir maintenant les regrouper. prenez par exemple ce code :

use App\Http\Controllers\Controller;
use App\Http\Requests\CommentRequest;
use App\Models\Post;
use App\Models\Comment;

On a autant de lignes que de déclarations. On va pouvoir simplifier ainsi :

use App\Http\{
    Controllers\Controller,
    Requests\CommentRequest
};
use App\Models\{
    Post,
    Comment
};

On y gagne en clarté !

Type des paramètres

Paramètres des fonctions

Avec PHP 5 on peut déclarer le type des paramètres pour les interface, les classes et les tableaux. Avec la version 7 on peut enfin aussi déclarer les types scalaires (int, float, string, bool).

Considérez par exemple cette fonction :

/**
 * Get the next comments for the specified post.
 *
 * @param  \App\Models\Post  $post
 * @param  integer $page
 * @return array
 */
public function comments(Post $post, $page)
{
    ...
}

On a le type du premier paramètre parce que c’est un objet, mais le second, qui est un entier, on ne peut pas le déclarer…

Avec PHP 7 on peut écrire :

public function comments(Post $post, int $page)

Mais PHP ne va pas vraiment vérifier que le type est bon (allez savoir pourquoi…), il va juste s’efforcer de transformer la valeur pour la rendre conforme au type, s’il y arrive… D’ailleurs il vaut mieux se méfier de la transformation des flottants en entiers qui peuvent réserver des surprises !

Mais on peut lui forcer la main pour qu’il devienne plus pointilleux :

declare(strict_types = 1);

Obligatoirement sur la première ligne du fichier PHP du code appelant.

Et là il ne laissera rien passer ! Bon, du coup c’est pas mal après d’intercepter l’erreur qui est de type TypeError.

Avec la version 7.1 est même apparu un pseudo type : iterable. Il arrive souvent qu’on transmettre un paramètre qui implémente l’interface Transversable, autrement dit qui acceptent l’utilisation de foreach. Dans cette catégorie on a les tableaux et les objets. On peut désormais indiquer à la fonction qu’on va lui transmettre ce genre de chose :

function action(iterable $elements)

Et rien n’empêche évidement de déclarer une valeur par défaut :

function action(iterable $elements = [])

Type du retour

La possibilité du typage s’étend à la valeur du retour de la fonction.

Voilà par exemple une fonction qui renvoie un string :

/**
 * Get .env element.
 *
 * @param string $key
 * @return string
 */
public function get($key)
{
    return $this->env->get ($key);
}

On ne précise pas ici le type de la valeur qu’on renvoie, juste dans les commentaires. Avec PHP 7 on peut écrire :

public function get($key) : string

Là aussi si on veut un comportement « strict » il faut le préciser de la même manière qu’on a vue ci-dessus.

On peut aussi déclarer le type de retour iterable.

Les opérateurs

L’opérateur de coalescence

Je suppose que vous avez souvent l’occasion d’écrire du code dans ce genre :

$category = isset($request->category) ? $request->category : 'aucune';

PHP 7 nous offre un nouvel opérateur :

$category = isset($request->category) ?? 'aucune';

Le résultat est le même mais c’est plus concis !

L’opérateur « spaceship »

Prenons ce code qui permet de classer des éléments :

usort($element, function ($a, $b) {
  return ($a < $b) ? -1 : (($a > $b) ? 1 : 0);
});

On a :

  • a < b : -1
  • a = b : 0
  • a > b : 1

Avec PHP 7 on peut simplifier la syntaxe :

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

Pratique ! Par contre ça me fait pas vraiment penser à un vaisseau spatial mais bon…

Classe anonyme

Avec PHP 5 on a hérité des fonctions anonymes qui sont il faut l’avouer bien pratiques surtout comme fonctions de rappel.

Avec PHP 7 ce sont maintenant les classes qui peuvent devenir anonymes. Autrement dit on n’a pas besoin de faire toutes les déclarations. Voici un exemple :

$maClasseAnonyme = new class($parametre) {
   private $parametre;
   public function __construct($parametre) {
     $this->parametre = $parametre;
   }
};

A part d’être anonymes on les utilise exactement comme les autres : implémentation d’interfaces, héritages, traits…

J’avoue que je ne vais pas m’en servir tous les jours…

Délégation des générateurs

Si vous n’êtes pas familiarisé avec les générateurs alors commencez par vous renseigner à leur sujet. C’est une façon de fournir des éléments d’un ensemble (itérateur) sans être obligé de construire au départ cet ensemble, donc de ne pas affecter outre mesure la mémoire.

Ce n’est pas clair ? Voici un exemple :

function entiers() {
    for ($i = 0; $i <= 10; ++$i) {
        yield $i;
    }
}

foreach (entiers() as $number) {
    echo "$number ";
}

// Résultat : 0 1 2 3 4 5 6 7 8 9 10

Oui c’est un peu idiot comme exemple mais c’est pour le principe !

La délégation c’est le fait pour un générateur d’en appeler un autre :

function entiers() {
    for ($i = 0; $i <= 5; ++$i) {
        yield $i;
    }
}

function nombres() {
    yield 100;
    yield from entiers ();
    yield 101;
    yield from entiers ();
}

foreach (nombres() as $number) {
    echo "$number ";
}

// Résultat : 100 0 1 2 3 4 5 101 0 1 2 3 4 5

Bon ce n’est pas plus malin comme exemple mais au moins ça donne le principe.

Les exceptions

Les exceptions ont été apportées à PHP à partir de la version 5. Mais ça ne concerne que les objets et toutes les autres erreurs de PHP ne passent pas par là. D’autre part il est en général fait usage d’un gestionnaire par défaut avec la fonction set_exception_handler.

PHP 7 apporte l’interface Throwable qui concerne les exceptions et, c’est nouveau, les erreurs, parce qu’elle se place en tête de la hiérarchie.

Prenons ce code :

function test($object)
{
  return $object->riendutout();
}
test(null);
echo 'Je marche encore !';

Si je l’exécute je vais tomber immanquablement sur une erreur fatale : Call to a member function riendutout() on null…

On va maintenant intercepter cette erreur :

function test($object)
{
  return $object->riendutout();
}
try
{
  test(null);
} catch(Error $e)
{
  echo $e->getMessage(), PHP_EOL;
}
echo 'Je marche encore !';

A l’exécution (PHP 7) on obtient :

Call to a member function riendutout() on null
Je marche encore !

On peut ainsi tout intercepter, même les divisions par zéro !

Syntaxe uniforme des variables

Avec PHP on peut utiliser des variables de variables, même si ce n’est pas très indiqué parce que ça complique la lecture du code et on peut en général facilement s’en passer.

Regardez ce code :

$identite = ['nom' => 'Pierre'];
$Pierre = 'Paul';
echo $$identite['nom'];

Avec PHP 5 vous obtenez : Pierre.

Avec PHP 7 vous obtenez plein d’erreurs : Array to string conversion…

Que se passe-t-il ?

PHP 7 apporte la « syntaxe uniforme des variables », un truc qui couvait depuis quelques années avec pas mal d’opposition à cause du cassage du code antérieur. Mais finalement c’est passé dans cette version.

Normalement l’interprétation se fait de gauche à droite, donc on devrait commencer par $$identite, puis ensuite prendre l’offset. Mais PHP 5 ne fait pas ça, il commence par traiter $identite[‘nom’]. Par contre comme PHP 7 va scrupuleusement de gauche à droite il y a un gros souci. Pour que ça fonctionne on doit écrire ${$identite[‘nom’]}. Et là maintenant ça fonctionne !

Ce changement n’est pas anodin si vous voulez migrer du code en PHP 7 !

Conclusion

On voit qu’il y a pas mal de nouveautés dans cette version, et je n’ai pas parlé des choses plus ou moins anodines que vous pouvez trouver dans le manuel…

 

 

Laisser un commentaire