PHP 7.4 a été publié en décembre dernier et l’équipe de développement du langage a présenté la nouvelle version majeure PHP 8. Nous y retrouvons entre autres :- de nouvelles fonctionnalités :
- un compilateur JIT ;
- les « union types » ;
- les attributs ;
- une nouvelle classe WeakMap ;
- les simplifications de code apportées par les nouveaux constructeurs ;
- de nouvelles fonctions :
- des changements qui auront un impact sur le code existant (Breaking changes) ;
- la gestion de l’incrémentation d’index négatifs dans les tableaux ;
- des modifications sur la gestion des erreurs ;
- des modifications sur les valeurs par défaut des directives d’initialisation de PHP ;
- des fonctions supprimées.
Cette version contient donc beaucoup de nouvelles fonctionnalités et d'optimisations, incluant les arguments nommés, les types d'union, attributs, promotion de propriétés de constructeur, l'expression match, l'opérateur nullsafe, JIT (Compilation à la Volée), et des améliorations dans le système de typage, la gestion d'erreur, et de cohérence.
Compilation juste à temps (JIT)
PHP 8 introduit deux moteurs de compilation JIT (juste à temps/compilation à la volée). Le Tracing JIT, le plus prometteur des deux, montre environ trois fois plus de performances sur des benchmarks synthétiques et 1,5-2 fois plus de performances sur certaines applications à longue durée d'exécution. Généralement les performances des applications sont identiques à PHP 7.4.
Contribution relative du JIT à la performance de PHP 8
Amélioration du système de typage et de la gestion d'erreur
- vérification de type plus sévère pour les opérateurs arithmétiques et bit à bit ;
- validation de méthode abstraite des traits ;
- signature valide des méthodes magiques ;
- reclassifications des avertissements du moteur ;
- erreur fatale pour des signatures de méthodes incompatibles ;
- l'opérateur @ ne silence plus les erreurs fatales ;
- héritages avec les méthodes privées ;
- type mixed ;
- type de retour static ;
- types pour les fonctions internes Discussion e-mail ;
- objets opaques au lieu de ressources pour les extensions Curl, Gd, Sockets, OpenSSL, XMLWriter, et XML.
Opérateur Nullsafe
Au lieu de faire des vérifications conditionnelles de nul, vous pouvez utiliser une chaîne d'appel avec le nouvel opérateur nullsafe. Qui lorsque l'évaluation d'un élément de la chaîne échoue, l'exécution de la chaîne complète est terminée et la chaîne entière évaluée à null.
Ainsi, dans PHP 7 vous aviez
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | $country = null; if ($session !== null) { $user = $session->user; if ($user !== null) { $address = $user->getAddress(); if ($address !== null) { $country = $address->country; } } } |
| Code PHP : | Sélectionner tout |
$country = $session?->user?->getAddress()?->country;
La nouvelle instruction match est similaire à switch et a les fonctionnalités suivantes :
- Match est une expression, signifiant que son résultat peut être enregistré dans une variable ou retourné ;
- les branches de match supportent uniquement les expressions d'une seule ligne, et n'a pas besoin d'une déclaration break ;
- Match fait des comparaisons strictes.
Ainsi, dans PHP 7 vous aviez
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | switch (8.0) { case '8.0': $result = "Oh no!"; break; case 8.0: $result = "This is what I expected"; break; } echo $result; //> Oh no! |
| Code PHP : | Sélectionner tout |
1 2 3 4 5 | echo match (8.0) { '8.0' => "Oh no!", 8.0 => "This is what I expected", }; //> This is what I expected |
Au lieu d'annotation PHPDoc pour une combinaison de type, vous pouvez utiliser les déclarations de types d'union native qui sont validées lors de l'exécution.
Ainsi, en PHP 7 vous aviez
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | /** @var int|float */ private $number; /** * @param float|int $number */ public function __construct($number) { $this->number = $number; } } new Number('NaN'); // Ok |
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 | class Number { public function __construct( private int|float $number ) {} } new Number('NaN'); // TypeError |
Moins de code redondant pour définir et initialiser les propriétés.
En PHP 7 vous aviez
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Point { public float $x; public float $y; public float $z; public function __construct( float $x = 0.0, float $y = 0.0, float $z = 0.0, ) { $this->x = $x; $this->y = $y; $this->z = $z; } } |
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 | class Point { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, ) {} } |
Au lieu d'annotations PHPDoc, vous pouvez désormais utiliser les métadonnées structurées avec la syntaxe native de PHP.
En PHP 7 vous aviez
| Code PHP : | Sélectionner tout |
1 2 3 4 5 | /** * @Route("/api/posts/{id}", methods={"GET", "HEAD"}) */ class User { |
| Code PHP : | Sélectionner tout |
1 2 3 | #[Route("/api/posts/{id}", methods: ["GET", "HEAD"])] class User { |
Les arguments nommés
Les arguments nommés permettent de passer des arguments à une fonction en fonction du nom du paramètre, plutôt que de la position du paramètre. Cela rend la signification de l'argument autodocumentée, rend les arguments indépendants de l'ordre et permet de sauter arbitrairement les valeurs par défaut.
Pour donner un exemple simple :
| Code PHP : | Sélectionner tout |
1 2 3 4 5 | //en utilisant des arguments de position: array_fill(0, 100, 50); //en utilisant des arguments nommés: array_fill(start_index: 0, num: 100, value: 50); |
| Code PHP : | Sélectionner tout |
array_fill(value: 50, num: 100, start_index: 0);
| Code PHP : | Sélectionner tout |
1 2 3 | htmlspecialchars($string, double_encode: false); //Revient à la même chose que htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); |
Ignorer les valeurs par défaut
Les arguments nommés vous permettent d'écraser directement uniquement les valeurs par défaut que vous souhaitez modifier. Prenons cet exemple :
| Code PHP : | Sélectionner tout |
1 2 3 4 | setcookie( name: 'test', expires: time() + 60 * 60 * 2, ); |
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | setcookie ( string $name, string $value = "", int $expires = 0, string $path = "", string $domain = "", bool $secure = false, bool $httponly = false, ) : bool |
Code autodocumenté
L'avantage de l'autodocumentation du code s'applique même lorsque vous n'ignorez pas les arguments facultatifs. Par exemple, comparez les deux lignes suivantes :
| Code PHP : | Sélectionner tout |
1 2 3 | array_slice($array, $offset, $length, true); // et array_slice($array, $offset, $length, preserve_keys: true); |
Initialisation d'objet
La RFC de promotion des propriétés du constructeur simplifie considérablement la déclaration des classes d'objets de valeur. Pour choisir l'un des exemples de cette RFC :
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // Partie de la représentation PHP AST class ParamNode extends Node { public function __construct( public string $name, public ExprNode $default = null, public TypeNode $type = null, public bool $byRef = false, public bool $variadic = false, Location $startLoc = null, Location $endLoc = null, ) { parent::__construct($startLoc, $endLoc); } } |
Il y a eu plusieurs tentatives pour rendre la construction d'objets plus ergonomique, comme le RFC Object Initializer et le RFC COPA. Cependant, toutes ces tentatives ont été refusées, car elles ne s'intègrent pas bien dans le langage, en raison d'une interaction défavorable avec des constructeurs ou des propriétés non publiques.
Les arguments nommés résolvent le problème d'initialisation des objets comme un effet secondaire, d'une manière qui s'intègre bien à la sémantique du langage existant.
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | new ParamNode("test", null, null, false, true); // devient: new ParamNode("test", variadic: true); new ParamNode($name, null, null, $isVariadic, $passByRef); // ou était-ce ? new ParamNode($name, null, null, $passByRef, $isVariadic); // qui devient new ParamNode($name, variadic: $isVariadic, byRef: $passByRef); // ou new ParamNode($name, byRef: $passByRef, variadic: $isVariadic); // et cela n'a plus d'importance! |
Options sécurisées et documentées
L'une des solutions de contournement courantes pour le manque d'arguments nommés est l'utilisation d'un tableau d'options. L'exemple précédent pourrait être réécrit pour utiliser un tableau d'options comme suit :
| Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class ParamNode extends Node { public string $name; public ExprNode $default; public TypeNode $type; public bool $byRef; public bool $variadic; public function __construct(string $name, array $options = []) { $this->name = $name; $this->default = $options['default'] ?? null; $this->type = $options['type'] ?? null; $this->byRef = $options['byRef'] ?? false; $this->variadic = $options['variadic'] ?? false; parent::__construct( $options['startLoc'] ?? null, $options['endLoc'] ?? null ); } } // Usage: new ParamNode($name, ['variadic' => true]); new ParamNode($name, ['variadic' => $isVariadic, 'byRef' => $passByRef]); |
- pour les constructeurs en particulier, cela exclut l'utilisation de la promotion de constructeur ;
- les options disponibles ne sont pas documentées dans la signature. Vous devez regarder l'implémentation ou phpdoc pour savoir ce qui est pris en charge et quels types il nécessite. Phpdoc ne fournit pas non plus de moyen universellement reconnu de documenter cela ;
- le type des valeurs d'option n'est pas validé sauf s'il est implémenté manuellement. Dans l'exemple ci-dessus, les types seront en fait validés en raison de l'utilisation de types de propriétés, mais cela ne suivra pas la sémantique PHP habituelle (par exemple, si la déclaration de classe utilise strict_types, les options seront également validées selon strict_types) ;
- à moins que vous ne fassiez tout votre possible pour vous protéger, le passage d'options inconnues sera validé silencieusement ;
- l'utilisation d'un tableau d'options nécessite une décision spécifique au moment de l'introduction de l'API. Si vous commencez sans en utiliser un, mais ajoutez ensuite des paramètres facultatifs supplémentaires et réalisez que l'utilisation d'un tableau d'options serait plus propre, vous ne pouvez pas effectuer le changement sans interrompre les utilisateurs d'API existants.
Les paramètres nommés fournissent les mêmes fonctionnalités que les tableaux d'options, sans aucun des inconvénients.
Source : PHP
Vous avez lu gratuitement 458 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.
