Ce qui est nouveaux dans PHP-7 partie 2

Publié le 24 février 2018 par Rhw @RevueHW

Comme vous le savez probablement déjà, PHP 7 est un fait, et il sortira cette année ! Ce qui fait que c’est le bon moment pour passer en revue les nouveautés et améliorations.

Dans la première partie de cette série, nous nous sommes intéressés à certaines des plus importantes réparations d’incohérences dans la version de PHP 7 ainsi que 2 des plus grandes nouvelles fonctionnalités.  Dans cet article nous allons nous intéresser à 6 autres grandes fonctionnalités qui arriveront avec PHP 7 et que vous aurez envie de connaître.

Unicode Codepoint Escape Syntax

L’ajout d’un nouveau caractère escape, \u, nous autorise à spécifier des points de code caractères Unicode (en hexadécimal) sans ambiguïté à l’intérieur des strings PHP :

La syntaxe utilisée est \u{CODEPOINT}, par exemple le cœur vert, peut être exprimé en tant que string PHP "\u{1F49A}".

Opérateur Coalesce vide (Null Coalesce Operator)

Un autre nouvel opérateur, le Null Coalesce Operator, est efficacement le mythique ifsetor. Il renverra l’opérande gauche s’il n’est pas NULL, sinon il renverra le droit. 

Ce qui est important c’est qu’il ne fait apparaître d’avertissement si l’opérande gauche est une variable non-existante. C’est comme isset() et c’est le contraire de l’opérateur short ternary ?:

Vous pouvez également enchainer les opérateurs pour renvoyer le premier non-null d’un set donné :

$config = $config ?? $this->config ?? 
static
::$defaultConfig;

Lier Closure sur un Call

Avec PHP 5.4 nous avons vu l’ajout de Closure->bindTo() et Closure ::bind() qui vous permet de changer la liaison de $this et le champ d’appel, ensemble, ou séparément, en créant un closure dupliqué.

PHP 7 apporte désormais un moyen facile de faire cela au moment du call, en liant à la fois $this et le champ d’appel au même objet avec l’ajout de Closure->call(). Cette méthode prend l’objet à son argument premier, suivi par tout argument qui passe dans le closure, comme cela :

class HelloWorld {
   private $greeting = "Hello";
}
$closure = function($whom) { echo $this->greeting . ' ' . $whom; }
$obj = new HelloWorld();
$closure->call($obj, 'World'); // Hello World

Déclarations de Use groupés (Group Use Declarations)

Si vous avez déjà eu à importer plusieurs classes depuis le même espace de noms (namespace), vous avez certainement été très content si votre IDE les auto-complétait pour vous. Pour les autres, et pour la brièveté, PHP 7 permet désormais des déclarations de Use groupés. Cela vous permet de rapidement spécifier plusieurs imports similaires avec plus de clarté :

// Originale
use Framework\Component\SubComponent\ClassA;
use Framework\Component\SubComponent\ClassB as ClassC;
use Framework\Component\OtherComponent\ClassD;
// Avec Group Use
use Framework\Component\{
   SubComponent\ClassA,
   SubComponent\ClassB as ClassC,
   OtherComponent\ClassD
};

Il peut aussi être utilisé avec des imports de type fonction et constant, à l’aide de la fonction use, et use const, ainsi que le support d’imports variés :

use Framework\Component\{
   SubComponent\ClassA,
   function OtherComponent\someFunction,
   const OtherComponent\SOME_CONSTANT
};

Améliorations des générateurs

 Expressions de renvoi générateur (Generator Return Expressions)

Il y a deux nouvelles fonctionnalités ajoutées aux générateurs. La première est Generator Return Expressions, qui vous permet désormais de renvoyer une valeur au moment de l’achèvement (réussi) d’un générateur.

Avant PHP 7, si vous essayiez de renvoyer quoi que ce soit, cela vous renvoyait une erreur. Cependant, vous pouvez maintenant appeler $generator->getReturn() pour récupérer une valeur.

Si le générateur n’a pas encore été renvoyé, ou a lancé une exception manquée, l’appel de $generator->getReturn() va lancer une exception.

Si le générateur est achevé mais qu’il n’y a pas eu de renvoi, alors null sera renvoyé.

Voici un exemple :

function gen() {
   yield "Hello";
   yield " ";
   yield "World!";
   return "Goodbye Moon!";
}
$gen = gen();
foreach ($gen as $value) {
   echo $value;
}
// Outputs "Hello" on iteration 1, " " on iterator 2, and "World!" on iteration 3
echo $gen->getReturn(); // Goodbye Moon!

Délégation générateur (Generator Delegation)

 La deuxième fonctionnalité est bien plus palpitante : Generator Delegation. Cela vous permet de renvoyer une autre structure itérable qui peut elle-même être traversée – que ce soit un array, un iterator, ou un autre generator.

Il est important de comprendre que l’itération de sous-structures est faite par la boucle la moins originale possible comme si c’était une simple structure plate, plutôt qu’une récursive.

Cela est également vrai lors de l’envoi de données ou d’exceptions dans un générateur. Elles sont passées directement dans la sous-structure comme si c’était contrôlé directement par l’appel.

Cela se fait en utilisant la syntaxe yield from <expression>, comme ceci :

function hello() {
   yield "Hello";
   yield " ";
   yield "World!";
   yield from goodbye();
}
function goodbye() {
   yield "Goodbye";
   yield " ";
   yield "Moon!";
}
$gen = hello();
foreach ($gen as $value) {
   echo $value;
}

Pour chaque itération, cela renverra :

1.   "Hello"

2.   " "

3.   "World!"

4.   "Goodbye"

5.   " "

6.   "Moon!"

Une autre mise en garde qu’il est bon de mentionner est que, du fait que la sous-structure peut céder ses propres clés, il est tout à faire possible que la même clé soit renvoyée pour des itérations multiples – c’est de votre responsabilité d’éviter cela, si cela compte pour vous.

Exceptions Moteur (Engine Exceptions)

La gestion des erreurs « fatal » et « catchable fatal » a toujours été impossible, ou du moins compliqué, avec PHP. Mais avec l’ajout des Engine Exceptions, beaucoup de ces erreurs renverront désormais des exceptions à la place.

Maintenant, quand une fatal ou catchable fatal error se produit, cela renverra une exception, vous permettant de vous en occuper correctement. Si vous ne vous en occupez pas du tout, cela résultera en une fatal error classique sous la forme d’une exception manquée.

Ces exceptions sont des objets \EngineException, et à l’inverse des exceptions userland, n’étendent pas la classe \Exception de base. Cela est fait pour s’assurer que le code existant qui attrape la classe \Exception ne commence pas en attrapant des fatal errors en avançant. Cela maintient par conséquent la compatibilité avec les versions antérieures.

A l’avenir, si vous souhaitez attraper à la fois les exceptions traditionnelles et les exceptions moteur, vous devrez attraper leur nouvelle classe parente, \BaseException.

En plus de cela, les parse errors dans le code eval() lanceront une \ParseException, alors que les type non assortis lanceront une \TypeException.

Voici un exemple :

try {
   nonExistentFunction();
} catch (\EngineException $e) {
   var_dump($e);
}
object(EngineException)#1 (7) {
  ["message":protected]=>
  string(32) "Call to undefined function nonExistantFunction()"
  ["string":"BaseException":private]=>
  string(0) ""
  ["code":protected]=>
  int(1)
  ["file":protected]=>
  string(17) "engine-exceptions.php"
  ["line":protected]=>
  int(1)
  ["trace":"BaseException":private]=>
  array(0) {
  }
  ["previous":"BaseException":private]=>
  NULL
}

En Résumé

PHP 7 va être génial!

Aller tester vos applications et commencer à songer à la migration des extensions.

Avez-vous déjà commencé à jouer avec PHP 7? Que pensez vous des nouvelles fonctionnalités? Y at-il quelque chose que vous n'êtes pas d'accord avec, ou que vous souhaitez avoir? Faites-nous savoir vos pensées!

Consulter notre comparatif d'hébergeurs web supportant PHP