URL: https://linuxfr.org/news/les-nouvelles-fonctionnalites-de-php-8 Title: Les nouvelles fonctionnalitĂ©s de PHP 8 Authors: MCMic Julien Jorge, Davy Defaud, Christophe "CHiPs" PETIT, Julien Boudry, BenMorel, Ysabeau đŸ§¶, Nils Ratusznik, theojouedubanjo, dourouc05, palm123 et ted Date: 2020ćčŽ10月05æ—„T14:16:45+02:00 License: CC By-SA Tags: php8, php et programmation Score: 41 La version 8 de PHP est sortie le 26 novembre 2020, nous allons donc voir ensemble les nouvelles fonctionnalitĂ©s qui ont Ă©tĂ© intĂ©grĂ©es dans cette version. Pour ne pas faire trop long, on se limitera aux choses nouvelles par rapport Ă  PHP 7.4, et on regardera les nouvelles fonctionnalitĂ©s principales, pour une liste exhaustive consultez le journal des modifications officiel. ---- [Article anglophone plus complet sur les nouveautĂ©s](https://stitcher.io/blog/new-in-php-8) [Annonce officielle](https://www.php.net/releases/8.0/en.php) [Journal des modifications dĂ©taillĂ©](https://www.php.net/ChangeLog-8.php) [Guide de migration](https://www.php.net/manual/en/migration80.php) ---- Nouvelles fonctionnalitĂ©s ========================= Syntaxe ------- ### Les unions de types PHP continue sa route vers un langage fortement typĂ©, en ajoutant le support des unions de types dans les spĂ©cificateurs de type de paramĂštres, de variables ou de retour de fonction. L’exemple de la [RFC](https://wiki.php.net/rfc/union_types_v2) : ```php class Number { private int|float $number; public function setNumber(int|float $number): void { $this->number = $number; } public function getNumber(): int|float { return $this->number; } } ``` Cela permet de mettre des informations de type Ă  des endroits oĂč l’on ne pouvait pas en mettre, lorsque plusieurs types diffĂ©rents sont acceptĂ©s ou retournĂ©s. ### Type « mixed » Toujours Ă  propos des types, le type `mixed` a Ă©tĂ© ajoutĂ© (_cf._ [RFC](https://wiki.php.net/rfc/mixed_type_v2)). Il indique qu’une variable peut ĂȘtre de n’importe quel type pris en charge par PHP. Ça peut sembler idiot puisque ça revient au mĂȘme que de ne pas mettre d’indication de type, mais ça permet au dĂ©veloppeur de l’indiquer explicitement, et il existe de nombreux cas de figure oĂč il est tout Ă  fait normal d’accepter tous les types (pour une fonction de sĂ©rialisation, par exemple). Cela peut aussi servir Ă  indiquer qu’une fonction doit retourner quelque chose, c’est donc le contraire de `:void` qui indique l’absence de retour. Aussi le mot-clĂ© `mixed` Ă©tait dĂ©jĂ  largement utilisĂ© dans la documentation de PHP. ### Type de retour « static » Puisqu’on parle de typage, il est maintenant possible d’indiquer « `static` » comme type de retour pour une mĂ©thode. Cela signifie qu’elle renvoie une instance de la classe sur laquelle la mĂ©thode est appelĂ©e. À noter qu’il existait dĂ©jĂ  le type de retour « `self` » pour indiquer qu’une mĂ©thode renvoie une instance de la classe Ă  laquelle elle appartient, ce qui n’est pas la mĂȘme chose. Voir la notion PHP de « _[late static binding](https://www.php.net/manual/fr/language.oop5.late-static-bindings.php)_ » [[RFC](https://wiki.php.net/rfc/static_return_type)]. Exemple : ```php class Test { public function create(): static { return new static(); } } ``` ### Les attributs Largement la plus grosse source de dĂ©bats internes pour cette version, les attributs ont fait leur apparition. Un attribut, parfois appelĂ© annotation dans d’autres langages, est une mĂ©tadonnĂ©e qui peut ĂȘtre ajoutĂ©e sur une fonction, une classe, un paramĂštre, une propriĂ©tĂ©... Cette mĂ©tadonnĂ©e est ensuite disponible par rĂ©flexion. AprĂšs ĂȘtre passĂ©e par `<>` et `@@Attribute`, c’est finalement la syntaxe `#[Attribute]` qui a Ă©tĂ© choisie au bout de quatre RFC, syntaxe dĂ©jĂ  utilisĂ©e par Rust. La notation `@Attribute` utilisĂ©e dans beaucoup d’autres langages n’était pas disponible, puisque l’opĂ©rateur `@` existe dĂ©jĂ  en PHP et sert Ă  ignorer les erreurs. RFC : - _[attributes](https://wiki.php.net/rfc/attributes)_ ; - _[attribute amendments](https://wiki.php.net/rfc/attribute_amendments)_ ; - _[shorter attribute syntax](https://wiki.php.net/rfc/shorter_attribute_syntax)_ ; - _[shorter attribute syntax change](https://wiki.php.net/rfc/shorter_attribute_syntax_change)_. ### Les paramĂštres nommĂ©s Un autre gros morceau de cette version est la prise en charge des paramĂštres nommĂ©s, ce qui signifie qu’il est possible d’indiquer la valeur d’un paramĂštre de fonction par son nom plutĂŽt que par sa position. Exemples tirĂ©s de la RFC : ```php htmlspecialchars($string, double_encode: false); // Au lieu de htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); array_fill(start_index: 0, num: 100, value: 50); // Au lieu de array_fill(0, 100, 50); // L’ordre n’est plus important, cette version est Ă©quivalente array_fill(value: 50, num: 100, start_index: 0); ``` Ce changement signifie que les noms des paramĂštres font maintenant partie de la signature des fonctions, et que renommer un paramĂštre de fonction peut casser du code qui utilise la fonction. Pour cette raison un gros travail d’amĂ©lioration et d’uniformisation des noms de paramĂštres a Ă©tĂ© fait pour PHP 8, et dans les versions suivantes un renommage sera considĂ©rĂ© comme cassant la compatibilitĂ© descendante [[RFC](https://wiki.php.net/rfc/named_params)]. ### La promotion de paramĂštres constructeurs Dans le but de simplifier l’écriture de classes simples servant simplement de schĂ©ma pour des objets contenant des donnĂ©es, et pour encourager leur utilisation plutĂŽt que celle de tableaux, il est maintenant possible de dĂ©clarer les propriĂ©tĂ©s d’une classe directement dans les paramĂštres du constructeur, afin de ne pas avoir Ă  les Ă©crire deux fois [[RFC](https://wiki.php.net/rfc/constructor_promotion)]. Exemple : ```php // Avant 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; } } // En PHP>=8.0 class Point { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, ) {} } ``` À noter que cette nouveautĂ© se marie particuliĂšrement bien avec les paramĂštres nommĂ©s : ```php class Circle { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, public float $r = 1.0, public string $name = '', public string $color = 'black', ) {} } $c1 = new Circle(x:12, y:13, r:5, name:'C1'); ``` ### OpĂ©rateur « nullsafe » Un nouvel opĂ©rateur `?->` a Ă©tĂ© ajoutĂ© [[RFC](https://wiki.php.net/rfc/nullsafe_operator)]. Il permet d’appeler une fonction ou de rĂ©cupĂ©rer une propriĂ©tĂ© de l’objet contenu dans la variable sans dĂ©clencher d’erreur si la variable est nulle. Cela permet par exemple de chaĂźner les appels de fonctions en autorisant une valeur nulle Ă  plusieurs endroits de la chaĂźne. Exemple : ```php // Le code suivant $country = null; if ($session !== null) { $user = $session->user; if ($user !== null) { $address = $user->getAddress(); if ($address !== null) { $country = $address->country; } } } // Peut maintenant ĂȘtre Ă©crit $country = $session?->user?->getAddress()?->country; ``` ### Mot‐clef « match » Le mot‐clef `match` a Ă©tĂ© ajoutĂ© comme alternative au `switch` lorsque l’on cherche Ă  retourner une valeur depuis chaque branche. Exemple : ```php // Avec switch switch ($mot) { case 'un': $nombre = 1; break; case 'deux': $nombre = 2; break; case 'trois': $nombre = 3; break; default: throw new Exception ('Mot invalide'); break; } // Avec match $nombre = match ($mot) { 'un' => 1, 'deux' => 2, 'trois' => 3, default => throw new Exception ('Mot invalide'), }; ``` Lisez attentivement la [RFC](https://wiki.php.net/rfc/match_expression_v2) pour la liste des subtiles diffĂ©rences avec `switch`. ### Nouvelles classes et interfaces La classe `WeakMap` a Ă©tĂ© ajoutĂ©e. Elle permet de gĂ©rer des correspondances avec des objets en clefs, qui n’empĂȘchent pas ces objets d’ĂȘtre dĂ©truits par le ramasse‐miettes. Quand un objet est dĂ©truit, la valeur qui lui est associĂ©e est simplement retirĂ©e de la `WeakMap` [[RFC](https://wiki.php.net/rfc/weak_maps)]. Une nouvelle classe `ValueError` est lancĂ©e quand une mĂ©thode reçoit un paramĂštre du bon type mais avec une valeur inappropriĂ©e, pour diffĂ©rencier du cas des `TypeError`, qui apparaissent quand le paramĂštre n’a pas le bon type. Une nouvelle interface `Stringable` permet de reconnaĂźtre les objets qui peuvent ĂȘtre transtypĂ©s en `string`. Elle est automatiquement implĂ©mentĂ©e par les classes qui dĂ©finissent la mĂ©thode magique `__toString()`. Cela permet, avec l’union des types, d’utiliser le groupe `string|Stringable` pour typer un paramĂštre qui accepte soit une chaĂźne de caractĂšres, soit n’importe quel objet qui peut se transtyper en chaĂźne de caractĂšres [[RFC](https://wiki.php.net/rfc/stringable)]. ### Autres nouveautĂ©s - il est maintenant possible d’obtenir le nom de la classe d’un objet en utilisant `$object::class`, le rĂ©sultat est le mĂȘme que `get_class($object)` [[RFC](https://wiki.php.net/rfc/class_name_literal_on_object)] ; - `new` et `instanceof` peuvent maintenant ĂȘtre utilisĂ©s avec des expressions arbitraires, sous la forme `new (expression)(...$args)` et `$obj instanceof (expression)` [[RFC](https://wiki.php.net/rfc/variable_syntax_tweaks)] ; - des changements ont Ă©tĂ© faits pour rendre la syntaxe des variables plus cohĂ©rentes, par exemple il est maintenant autorisĂ© d’écrire `Foo::BAR::$baz` [[RFC](https://wiki.php.net/rfc/variable_syntax_tweaks)] ; - les [_traits_](https://fr.wikipedia.org/wiki/Trait_(programmation)) peuvent maintenant dĂ©finir des mĂ©thodes privĂ©es [[RFC](https://wiki.php.net/rfc/abstract_trait_method_validation)] ; - `throw` peut dĂ©sormais ĂȘtre utilisĂ© comme une expression [[RFC](https://wiki.php.net/rfc/throw_expression)] ; - une virgule supplĂ©mentaire est autorisĂ©e Ă  la fin des listes de paramĂštres, pour faciliter les choses quand on Ă©crit un paramĂštre par ligne (notamment pour mieux versionner dans ces cas‐lĂ ) [[RFC](https://wiki.php.net/rfc/trailing_comma_in_parameter_list)] ; - il est maintenant possible d’écrire `catch (Exception)` pour capturer une exception sans la stocker dans une variable [[RFC](https://wiki.php.net/rfc/non-capturing_catches)] ; - les mĂ©thodes privĂ©es dĂ©clarĂ©es sur une classe parente ne contraignent plus la signature des mĂ©thodes sur la classe fille (Ă  l’exception des constructeurs finals privĂ©s) [[RFC](https://wiki.php.net/rfc/inheritance_private_methods)] ; - un nombre variable de paramĂštres de mĂ©thode peut maintenant ĂȘtre remplacĂ© par un paramĂštre variadique lors de l’hĂ©ritage, tant que les types sont compatibles ; ceci est par exemple possible : ```php class A { public function method(int $many, string $parameters, $here) {} } class B extends A { public function method(...$everything) {} } ``` BibliothĂšque standard --------------------- ### printf() Les fonctions de la famille `printf()` supportent maintenant les spĂ©cificateurs de format `%h` et `%H`. Ils font pareil que `%g` et `%G` mais utilisent toujours le point comme sĂ©parateur des dĂ©cimales au lieu de se fier Ă  la rĂ©gionalisation (_locale_) configurĂ©e via `LC_NUMERIC`. Il est Ă©galement maintenant possible d’utiliser `*` comme largeur de champ ou prĂ©cision de flottant, auquel cas la largeur/prĂ©cision est passĂ©e comme argument Ă  la fonction. Passer `-1` comme prĂ©cision pour `%g`, `%G`, `%h` et `%H` permet de reproduire le comportement par dĂ©faut de PHP pour les flottants : ```php printf("%.*H", (int) ini_get("precision"), $float); printf("%.*H", (int) ini_get("serialize_precision"), $float); ``` ### proc_open() La fonction `proc_open()` gĂšre maintenant des descripteurs de pseudo‐terminal (PTY) ; l’exemple suivant attache _stdin_, _stdout_ et _stderr_ au mĂȘme PTY : ```php $proc = proc_open($command, [['pty'], ['pty'], ['pty']], $pipes); ``` `proc_open()` gĂšre maintenant les _[sockets](https://fr.wikipedia.org/wiki/Berkeley_sockets)_. L’exemple suivant attache des sockets distincts pour _stdin_, _stdout_ et _stderr_ : ```php $proc = proc_open($command, [['socket'], ['socket'], ['socket']], $pipes); ``` Contrairement aux tubes (_pipes_), les _sockets_ n’ont pas de problĂšmes de blocage d’entrĂ©es‐sorties sous Windows. Cependant, tous les programmes ne fonctionnent pas forcĂ©ment correctement avec des _sockets_. ### Fonctions de tri Les diffĂ©rentes fonctions de tri sont maintenant stables, ce qui signifie que les Ă©lĂ©ments qui sont Ă©gaux selon la fonction de comparaison conservent maintenant leur ordre relatif d’avant le tri. Il y a un lĂ©ger coĂ»t en performances mais cela peut Ă©viter les mauvaises surprises [[RFC](https://wiki.php.net/rfc/stable_sorting)]. ### Nouvelles fonctions sur les chaĂźnes de caractĂšres Les fonctions `str_contains()`, `str_starts_with()` et `str_ends_with()` ont Ă©tĂ© ajoutĂ©es, permettant de dĂ©terminer respectivement si une chaĂźne de caractĂšres contient, commence par et finit par une autre chaĂźne. Ce sont des opĂ©rations trĂšs courantes, et s’il n’était pas difficile de les implĂ©menter en PHP, le fait qu’il y ait plusieurs façons de faire pouvait perturber les dĂ©veloppeurs. RFC : - _[str_contains()](https://wiki.php.net/rfc/str_contains)_ ; - _[add str_starts_with() and str_ends_with() functions](https://wiki.php.net/rfc/add_str_starts_with_and_ends_with_functions)_. ### OpĂ©rations sur les tableaux Les fonctions `array_diff()`, `array_intersect()` et leurs variations peuvent maintenant ĂȘtre utilisĂ©es avec un seul tableau en paramĂštre. Cela facilite leur utilisation avec l’opĂ©rateur `...` : ```php // Fonctionne mĂȘme si $excludes est vide array_diff($array, ...$excludes); // Fonctionne mĂȘme si $arrays contient un seul tableau array_intersect(...$arrays); ``` Extensions ---------- ### Hash Les objets HashContext peuvent maintenant ĂȘtre sĂ©rialisĂ©s. ### OpenSSL Ajout du prise en charge de la RFC 5652, « _Cryptographic Message Syntax_ (CMS) », avec des fonctions pour chiffrement, dĂ©chiffrement, signature, vĂ©rification et lecture. L’API est similaire Ă  celle pour PKCS#7 avec l’ajout de nouvelles constantes : `OPENSSL_ENCODING_DER`, `OPENSSL_ENCODING_SMIME` et `OPENSSL_ENCODING_PEM`. Performances ------------ ### JIT Un compilateur Ă  la volĂ©e (JIT — _Just In Time_) a Ă©tĂ© ajoutĂ© dans PHP afin de permettre, dans certains cas, d’augmenter les performances. La fonctionnalitĂ© est dĂ©sactivĂ©e par dĂ©faut et n’apporte pas grand’chose dans le cadre d’application Web classiques. En revanche, pour des usages plus gourmands en calcul, par exemple un calcul de fractal qui a Ă©tĂ© utilisĂ© pour les dĂ©mos, le compilateur Ă  la volĂ©e apporte un gain de performance trĂšs important. L’idĂ©e est donc de rendre PHP plus viable pour des usages pour lesquels il Ă©tait trop lent auparavant.

AltStyle ă«ă‚ˆăŁăŠć€‰æ›ă•ă‚ŒăŸăƒšăƒŒă‚ž (->ă‚ȘăƒȘă‚žăƒŠăƒ«) /