PHP 7.0.0

php7

Vous avez certainement entendu parler de la nouvelle version majeure de PHP, non pas la 6 la 7 !! Celle qui est censée vous éviter de regarder du côté de Hack ou tout autre conccurent. Je vais tenter de vous présenter à travers cet article les nouveautés qui m’ont parues les plus intéressantes.

Paramètres typés

La grande nouveauté, et certainement la plus attendue de PHP7 est le typage des paramètres scalaire. Avant PHP7, vous utilisiez surement le typage des paramètres pour les objets et tableaux. Sachez qu’avec l’arrivé de PHP7, il est maintenant possible de préciser le type de variables scalaire attendues dans la définition de votre fonction (int, float, bool, string).

<?php
declare(strict_types = 1);

function foo(string $holiday)
{
}

La première instruction, permet d’activer le mode strict, qui aura comme impact de lever une fatale erreur si la variable injectée n’est pas du type attendu:

<?php
declare(strict_types = 1);

function foo(float $price)
{
    return $price * 1.2;
}

foo('10.0'); 
// Fatal error: Argument 1 passed to foo() must be of the type float, string given, ...

A savoir

1) La directive declare(strict_types = 1) n’est prise en compte que dans le fichier courant.

2) Les alias integer et boolean ne sont pas disponibles.

3) Le type float accepte un int en mode strict. (function foo(float $pricer); foo(10);)

4) Si le mode strict n’est pas actif, les valeurs seront converties:

<?php

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

echo foo(0.5, 1.5); // 1

5) Le mode strict affecte aussi les fonctions “natives”:

<?php 
declare(strict_types = 1);

echo strlen(150); 
// Fatal error: strlen() expects parameter 1 to be string, integer given

Déclaration du retour

Cette nouvelle fonctionnalité va de paire avec la précédente. Il sera donc possible de préciser le type de retour d’une fonction.

<?php 
declare(strict_types = 1);

function random(): int {
    return mt_rand(0, 50);
}

Dans l’exemple précédent, j’ai donc déclaré une fonction random qui devra retourner une valeur de type int. En mode strict, une fatale erreur sera levée si le type du retour n’est pas correct.

A savoir

1) Les mêmes règles que pour le typage des paramètres s’appliquent concernant la directive declare(strict_types = 1).

2) La fonction ceil, qui retourne l’entier supérieur du nombre, retourne en réalité un float:

<?php 
declare(strict_types = 1);

function myCeil(float $price): int {
    return ceil($price);
}

echo myCeil(10.5);
//Fatal error: Return value of myCeil() must be of the type integer, float returned

Opérateur à 3 issue

Il s’agit de l’ajout d’un nouvel opérateur de comparaison <=>, appelé opérateur à 3 issues ou vaisseau spatial dû à sa forme. Actuellement, lorsque nous utilisons un opérateur de comparaison (>, >=, <, <=, ===  …), le résultat obtenu est binaire. La particularité de cet opérateur, est que le résultat pourra retourner 3 valeurs distinctes: -1 0 ou 1.

L’opérateur retourne 0 si les 2 variables sont identiques, -1 si la variable de gauche est inférieure  et 1 si elle est supérieure. L’opérateur fonctionne avec tous les types de variables.

echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1

Bon, c’est bien beau tout ça mais à quoi ça sert ? Cet opérateur est en fait principalement utilisé pour les tries comme ceci:

<?php 

$users = [
    ['name' => 'Pierre'],
    ['name' => 'Paul'],
    ['name' => 'Jacques'],
    ['name' => 'Jean']
];

usort($users, function ($a, $b) { 
    return $a['name'] <=> $b['name']; 
});

Nouvel opérateur ternaire

Ce nouvel opérateur vient compléter celui d’Elvis. L’opérateur Elvis ($value = $value ?: ‘new value’;) vérifie si le contenu de la variable est égale à null, et si ce n’est pas le cas, il va conserver la valeur actuelle de la variable, sinon utiliser celle comprise dans le else (‘new_value’).

Le problème avec cet opérateur, est qu’il ne vérifie pas l’existence de la variable:

<?php 

$value = $value ?: 'new value'; // Notice: Undefined variable: value
var_dump($value); //string(9) "new value"

C’est pourquoi un nouvel opérateur ?? a fait son apparition. Il permet, avant de vérifier le contenu d’une variable, de vérifier son existence, ce qui évitera les warnings:

<?php 

$value = $value ?? 'new value';
var_dump($value);

A savoir

Il est possible de le chaîner comme ceci:

<?php 

$_GET['query'] = 'php';
$filter = $_GET['category'] ?? $_GET['brand'] ?? $_GET['query'];
var_dump($filter); // string(3) "php"

EngineException && ParseException

(edit 2015-10-13) Nouvelle RFC concernant les exceptions: https://wiki.php.net/rfc/throwable-interface

Voilà une RFC que j’apprécie vraiment, il s’agit de l’ajout de 2 nouvelles exceptions, qui vont nous permettre de pouvoir catcher les fatales erreurs .

Motivations:

  • L’arrêt des démons: Si vous avez des démons qui tourne en PHP, il vous est certainement déjà arrivé de les voir se faire stopper par une fatal error. Actuellement il n’est pas possible de passer outre, votre démon va s’arrêter sans que vous puissiez faire quoi que ce soit.
  • La fonction error_handle n’est pas appelée lors d’une fatale erreur.
  • Les destructeurs des classes ne sont pas appelés.
  • Les bloques finally ne sont pas invoqué.

Ci-dessous un exemple, avec un eval faisant appel à une fonction foo() non existante:

try {
    eval('echo foo();');
} catch(EngineException $e) {
    echo "ENGINE: ".$e->getMessage();
}

// ENGINE: Call to undefined function foo()

Un second exemple avec une parse error:

try {
    eval('echo foo()');
} catch(ParseException $e) {
    echo "PARSE: ".$e->getMessage();
}

// PARSE: syntax error, unexpected end of file, expecting ',' or ';'

A savoir

1) Ces 2 exceptions sont au même niveau hiérarchique que la classe Exception (elles héritent de BaseException):

try {
    eval('echo foo()');
} catch(Exception $e) {
   // Ne passe pas ici !
} catch(ParseException $e) {     
    echo "PARSE: ".$e->getMessage(); 
} 
// PARSE: syntax error, unexpected end of file, expecting ',' or ';'

Déclaration d’espace de noms groupés

Une RFC pour laquelle j’étais contre, car je n’y vois franchement pas grand intérêt, mais je vous la présente quand même. Il s’agit en fait d’offrir la possibilité de grouper les espaces de noms ayant le même préfixe comme ceci:

<?php 

use FooLibrary\Bar\Baz\{ ClassA, ClassB, ClassC, ClassD as Fizbo };

La syntaxe n’est pas déconnante, c’est celle que vous utilisez certainement déjà sous linux: mv my_file.{php,old} mais ça ne fait pas de moi un convaincu 🙂

Et du ménage !

Suppression du warning levé lorsque nous utilisons les fonctions date sans avoir configuré la directive date.timezone. (rfc).

Suppression des tags ASP et Script: <%<%=, <script> … (rfc).

Suppression des SAPI et extensions dépréciées ou non maintenues (rfc).

Les performances

Un petit coup d’œil ici http://www.reddit.com/r/PHP/comments/305ck6/real_world_php_70_benchmarks/

Suivez l’aventure PHP7

Vous pouvez commencer par suivre les RFC sur le site officiel.

Vous pouvez ensuite vous abonnez à php-internals@lists.afup.org, et discuter avec d’autres développeurs sur les RFC en cours de vote, et donner votre avis.

Si vous souhaitez jouer avec PHP7: https://github.com/GuillaumeDievart/vagrant-centos-php7

 

Voilà, je pense avoir fait le tour des fonctionnalités qui m’ont parues les plus intéressantes. Si vous souhaitez voir toutes les nouveautés de PHP7 c’est par là: https://wiki.php.net/rfc#php_70.

J’essaierai d’enrichir cet article au fur et à mesure que de nouvelles RFC soit implémentées.

No Comments

Sorry, the comment form is closed at this time.