Savoir à quoi s’attendre peut vous aider à vous préparer à la dernière version de PHP. En vous renseignant sur les nouvelles fonctionnalités et celles obsolètes, vous pouvez comprendre comment la mise à jour peut affecter votre développement. Cette connaissance peut également vous aider à vous préparer pour la sortie éventuelle.
Dans cette optique, passons en revue les fonctionnalités, les améliorations de performances, les modifications et les dépréciations.
De PHP 8.0 à PHP 8.1
Il est important de savoir à quelles modifications s’attendre avant la mise à niveau.
PHP 8.0
PHP 8.0, sorti en novembre 2020, a apporté une poignée de fonctionnalités essentielles. En plus des améliorations de la syntaxe et des performances, la version comprenait :
- Des arguments nommés
- la syntaxe de correspondance
- les types de syndicats
- Promotion Propriété Constructeur
- JIT (qui affecte la façon dont PHP exécute le code source)
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); |
L'ordre dans lequel les arguments nommés sont passés n'a pas d'importance. L'exemple ci-dessus les passe dans le même ordre qu'ils sont déclarés dans la signature de la fonction, mais tout autre ordre est également possible.
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.
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.
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! |
Et son équivalent en PHP 8
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 |
PHP 8.1
Un an plus tard est arrivé PHP 8.1, la dernière version majeure de PHP. Cette mise à jour comprend des fonctionnalités importantes, telles que :
- Types d’intersections
- Propriétés en lecture seule
- Énumérations
- le type de retour never
Les énumérations ou « Enums » permettent à un développeur de définir un type personnalisé limité à l'une des valeurs possibles parmi un nombre discret. Cela peut être particulièrement utile lors de la définition d'un modèle de domaine, car cela permet de « rendre les états invalides non représentables ».
Les énumérations apparaissent dans de nombreux langages avec une variété de fonctionnalités différentes. En PHP, les Enums sont un type particulier d'objet. L'Enum lui-même est une classe et ses cas possibles sont tous des objets à instance unique de cette classe. Cela signifie que les cas Enum sont des objets valides et peuvent être utilisés partout où un objet peut être utilisé, y compris les vérifications de type.
L'exemple le plus populaire d'énumérations est le type booléen intégré, qui est un type énuméré avec les valeurs légales true et false. Les énumérations permettent aux développeurs de définir leurs propres énumérations arbitrairement robustes.
Dans PHP 8.1, les énumérations sont limitées aux « énumérations d'unités », c'est-à-dire aux énumérations qui sont elles-mêmes une valeur, plutôt qu'une simple syntaxe sophistiquée pour une constante primitive, et n'incluent pas d'informations associées supplémentaires. Cette capacité offre une prise en charge considérablement étendue de la modélisation des données, des définitions de types personnalisées et du comportement de style monade. Les énumérations permettent la technique de modélisation consistant à « rendre les états invalides non représentables », ce qui conduit à un code plus robuste avec moins de tests exhaustifs.
Les responsables du langage recommandent d'utiliser les énumérations au lieu d'un ensemble de constantes et d'obtenir ainsi une validation prête à l'emploi.
Par exemple, avant PHP 8.1, vous pouviez écrire :
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 | class Status { const DRAFT = 'draft'; const PUBLISHED = 'published'; const ARCHIVED = 'archived'; } function acceptStatus(string $status) {...} |
Ce code est optimisé en PHP 8.1 avec les énumérations :
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 | enum Status { case Draft; case Published; case Archived; } function acceptStatus(Status $status) {...} |
Propriétés en lecture seule readonly : Les objets valeur sont souvent immuables : les propriétés sont initialisées une fois dans le constructeur et ne doivent pas être modifiées par la suite. PHP n'a actuellement aucun moyen d'appliquer cette contrainte. L'alternative la plus proche consiste à déclarer la propriété private et à n'exposer qu'un getter public
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | class User { public function __construct( private string $name ) {} public function getName(): string { return $this->name; } } |
Cela ne rend pas réellement la propriété en lecture seule, mais cela resserre la portée où une modification pourrait se produire sur une seule déclaration de classe. Malheureusement, cela nécessite l'utilisation d'un passe-partout getter, ce qui entraîne une moins bonne ergonomie.
La prise en charge des propriétés en lecture seule de première classe vous permet d'exposer directement les propriétés publiques en lecture seule, sans craindre que les invariants de classe puissent être rompus par une modification externe :
Code PHP : | Sélectionner tout |
1 2 3 4 5 | class User { public function __construct( public readonly string $name ) {} } |
Aussi, cette proposition a été retenue : une propriété en lecture seule ne peut être initialisée qu'une seule fois, et uniquement à partir de la portée où elle a été déclarée. Toute autre affectation ou modification de la propriété entraînera une exception d'erreur.
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Test { public readonly string $prop; public function __construct(string $prop) { // Legal initialization. $this->prop = $prop; } } $test = new Test("foobar"); // Legal read. var_dump($test->prop); // string(6) "foobar" // Illegal reassignment. It does not matter that the assigned value is the same. $test->prop = "foobar"; // Error: Cannot modify readonly property Test::$prop |
La suite concerne PHP 8.2.
null, true et false en tant que types autonomes (Release Candidate)
PHP 8.2 ajoute trois nouveaux types — ou quelque chose qui y ressemble. Techniquement null, true et false pourraient être considérés comme des types valides en eux-mêmes. Des exemples courants sont les fonctions intégrées de PHP, où false est utilisé comme type de retour lorsqu'une erreur se produit. Par exemple dans file_get_contents*:
Code PHP : | Sélectionner tout |
file_get_contents(/* */): string|false
Avant PHP 8.2, vous pouviez déjà utiliser false avec d'autres types comme union ; mais maintenant, il peut également être utilisé comme type autonome*:
Code PHP : | Sélectionner tout |
1 2 3 4 | function alwaysFalse(): false { return false; } |
Il en va de même pour true et null.
Classes en lecture seule (RFC)
Les propriétés en lecture seule ont été introduites dans PHP 8.1. Cette RFC s'appuie sur eux et ajoute du sucre syntaxique pour rendre toutes les propriétés de classe en lecture seule à la fois. Au lieu d'écrire ceci :
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | class Post { public function __construct( public readonly string $title, public readonly Author $author, public readonly string $body, public readonly DateTime $publishedAt, ) {} } |
Vous pouvez maintenant écrire ceci :
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | readonly class Post { public function __construct( public string $title, public Author $author, public string $body, public DateTime $publishedAt, ) {} } |
Fonctionnellement, rendre une classe en lecture seule est entièrement identique à rendre chaque propriété en lecture seule ; mais cela empêchera également l'ajout de propriétés dynamiques sur une classe*:
Code PHP : | Sélectionner tout |
1 2 3 | $post = new Post(/* */); $post->unknown = 'wrong'; |
Envoyé par Résultat
En parlant de propriétés dynamiques*: c'est un changement pour le mieux, mais cela fera un peu mal. Les propriétés dynamiques sont obsolètes en PHP 8.2 et lèveront une ErrorException en PHP 9.0. Que sont les propriétés dynamiques, demandez-vous*? Ce sont des propriétés qui ne sont pas présentes sur un objet, mais qui sont néanmoins définies ou obtenues*:
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 | class Post { public string $title; } // $post->name = 'Name'; |
Gardez à l'esprit que les classes implémentant __get et __set fonctionneront toujours comme prévu*:
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Post { private array $properties = []; public function __set(string $name, mixed $value): void { $this->properties[$name] = $value; } } // $post->name = 'Name'; |
Il en va de même pour les objets de stdClass, ils continueront à prendre en charge les propriétés dynamiques.
Il est indéniable qu'il y a des développeurs qui se sont appuyés sur des propriétés dynamiques et qui ne sont pas satisfaits de ce changement. Mais l'équipe pense que ces développeurs gagneraient à approfondir l'analyse statique.
Et juste au cas où vous ne voudriez pas ces avertissements lors de la mise à niveau vers PHP 8.2, vous pouvez faire plusieurs choses.
Vous pouvez utiliser l'attribut #[AllowDynamicProperties] sur les classes qui doivent toujours autoriser ces propriétés*:
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | #[AllowDynamicProperties] class Post { public string $title; } // $post->name = 'Name'; // All fine |
Ou vous pouvez simplement désactiver les avertissements d'obsolescence. Cela n'est pas recommandé, car vous aurez des problèmes avec PHP 9.0, mais voici comment désactiver les avertissements de dépréciation en PHP :
Code PHP : | Sélectionner tout |
error_reporting(E_ALL ^ E_DEPRECATED);
Types de forme normale disjonctive (DNF pour Disjunctive Normal Form) en RFC
Les types DNF nous permettent de combiner les types d'union et d'intersection, en suivant une règle stricte*: lors de la combinaison de types d'union et d'intersection, les types d'intersection doivent être regroupés avec des crochets. En pratique, cela ressemble à ceci :
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | function generateSlug((HasTitle&HasId)|null $post) { if ($post === null) { return ''; } return strtolower($post->getTitle()) . $post->getId(); } |
Dans ce cas, (HasTitle&HasId)|null est le type DNF.
C'est un ajout intéressant, d'autant plus que cela signifie que nous pouvons désormais avoir des types d'intersection nullables, ce qui est probablement le cas d'utilisation le plus important pour cette fonctionnalité.
Constantes dans les traits (rfc)
Vous pouvez désormais utiliser des constantes dans les traits*:
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | trait Foo { public const CONSTANT = 1; public function bar(): int { return self::CONSTANT; } } |
Vous ne pourrez pas accéder à la constante via le nom du trait, ni de l'extérieur du trait, ni de l'intérieur de celui-ci.
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | trait Foo { public const CONSTANT = 1; public function bar(): int { return Foo::CONSTANT; } } Foo::CONSTANT; |
Vous pouvez cependant accéder à la constante via la classe qui utilise le trait, étant donné qu'elle est publique*:
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 | class MyClass { use Foo; } MyClass::CONSTANT; // 1 |
Source : PHP
Voir aussi :
PHP 8 est disponible et s'accompagne d'optimisations et de nouvelles fonctionnalités, incluant entre autres les arguments nommés, les types d'union, l'opérateur nullsafe, la compilation JIT
PHP 8.1 est disponible. Cette version permet d'obtenir une référence à n'importe quelle fonction et apporte le type de retour never