PHP 8 est disponible et s'accompagne de nouvelles fonctionnalités et d'optimisations, incluant les arguments nommés
les types d'union, l'opérateur nullsafe, la compilation JIT
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 ;
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.
585098
Contribution relative du JIT à la performance de PHP 8
Amélioration du système de typage et de la gestion d'erreur
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
$country = null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
Dans PHP 8 vous avez son équivalent :
$country = $session?->user?->getAddress()?->country;
Expression match
La nouvelle instruction match est similaire à switch et a les fonctionnalités suivantes :
Ainsi, dans PHP 7 vous aviez
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
echo match (8.0) {
'8.0' => "Oh no!",
8.0 => "This is what I expected",
};
//> This is what I expected
Types d'union
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
/** @var int|float */
private $number;
/**
* @param float|int $number
*/
public function __construct($number) {
$this->number = $number;
}
}
new Number('NaN'); // Ok
Et son équivalent en PHP 8
class Number {
public function __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
Promotion de propriétés de constructeur
Moins de code redondant pour définir et initialiser les propriétés.
En PHP 7 vous aviez
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 vous avez
class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
Attributs
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
/**
* @Route("/api/posts/{id}", methods={"GET", "HEAD"})
*/
class User
{
En PHP 8 vous avez
#[Route("/api/posts/{id}", methods: ["GET", "HEAD"])]
class User
{
585097
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 :
//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 :
array_fill(value: 50, num: 100, start_index: 0);
Il est possible de combiner des arguments nommés avec des arguments positionnels normaux et il est également possible de ne spécifier que certains des arguments optionnels d'une fonction, quel que soit leur ordre :
htmlspecialchars($string, double_encode: false);
//Revient à la même chose que
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
Il y a plusieurs avantages aux arguments nommés.
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 :
setcookie(
name: 'test',
expires: time() + 60 * 60 * 2,
);
Sa signature de méthode est en fait la suivante :
setcookie (
string $name,
string $value = "",
int $expires = 0,
string $path = "",
string $domain = "",
bool $secure = false,
bool $httponly = false,
) : bool
Dans cet exemple, nous n'avions pas besoin de définir $value d'un cookie, mais nous devions définir une heure d'expiration. Les arguments nommés ont rendu cet appel de méthode un peu plus concis.
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 :
array_slice($array, $offset, $length, true);
// et
array_slice($array, $offset, $length, preserve_keys: true);
Si cet exemple n'était pas écrit en ce moment, un développeur n'aurait pas su ce que fait le quatrième paramètre de array_slice (ou même qu'il existe en premier lieu).
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 :
// 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);
}
}
Les constructeurs en particulier ont souvent un nombre plus grand que la moyenne de paramètres dont l'ordre n'a pas de signification particulière, et qui sont généralement par défaut. Bien que la promotion du constructeur simplifie la déclaration de classe, elle n'aide pas l'instanciation d'objet réelle.
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.
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!
L'avantage des arguments nommés pour l'initialisation des objets est en surface le même que pour les autres fonctions, cela a juste tendance à avoir plus d'importance dans la pratique ici.
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 :
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]);
Bien que cela fonctionne, et soit déjà possible aujourd'hui, cela présente de nombreux inconvénients :
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 5 962 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.
