Sorti le 25 novembre 2021, PHP 8.1 est enfin là, avec plusieurs fonctionnalités intéressantes.

Dans cet article, nous allons couvrir en détail les nouveautés de PHP 8.1. Qu’il s’agisse de ses nouvelles fonctionnalités, d’améliorations des performances, de changements importants ou de dépréciations, nous allons les passer en revue en profondeur.

Ne bougez pas !

Nouvelles fonctionnalités de PHP 8.1

Commençons par couvrir toutes les nouvelles fonctionnalités de PHP 8.1. C’est une sacrée liste.

Types d’intersection purs

PHP 8.1 ajoute la prise en charge des types d’intersection. C’est similaire aux types d’union introduits dans PHP 8.0, mais leur utilisation prévue est exactement l’inverse.

Pour mieux comprendre son utilisation, rafraîchissons la façon dont les déclarations de type fonctionnent en PHP.

Essentiellement, vous pouvez ajouter des déclarations de type aux arguments des fonctions, aux valeurs de retour et aux propriétés des classes. Cette affectation est appelée indication de type et garantit que la valeur est du bon type au moment de l’appel. Sinon, une TypeError est immédiatement émise. En retour, cela vous aide à mieux déboguer le code.

Cependant, la déclaration d’un type uniques a ses limites. Les types d’union vous aident à surmonter cela en vous permettant de déclarer une valeur avec plusieurs types, et l’entrée doit satisfaire au moins un des types déclarés.

D’autre part, la RFC décrit les types d’intersection comme ceci :

Un « type d’intersection » exige qu’une valeur satisfasse plusieurs contraintes de type au lieu d’une seule.

…les types d’intersection purs sont spécifiés à l’aide de la syntaxe T1&T2&… et peuvent être utilisés dans toutes les positions où les types sont actuellement acceptés…

Notez l’utilisation de l’opérateur & (AND) pour déclarer les types d’intersection. En revanche, nous utilisons l’opérateur | (OR) pour déclarer les types d’union.

L’utilisation de la plupart des types standard dans un type d’intersection donnera un type qui ne pourra jamais être rempli (par exemple, integer et string). Par conséquent, les types d’intersection ne peuvent inclure que des types de classe (c’est-à-dire des interfaces et des noms de classe).

Voici un exemple de code montrant comment vous pouvez utiliser les types d’intersection :

classe A {
    private Traversable&Countable $countableIterator;
 
    public function setIterator(Traversable&Countable $countableIterator) : void {
        $this->countableIterator = $countableIterator;
    }
 
    public function getIterator() : Traversable&Countable {
        retourne $this->countableIterator;
    }
}

Dans le code ci-dessus, nous avons défini une variable countableIterator comme une intersection de deux types : Traversable et Countable. Dans ce cas, les deux types déclarés sont des interfaces.

Les types d’intersection sont également conformes aux règles standard de variance PHP déjà utilisées pour la vérification des types et l’héritage. Mais il existe deux règles supplémentaires concernant la façon dont les types d’intersection interagissent avec le sous-typage. Vous pouvez en savoir plus sur les règles de variance des types d’intersection dans sa RFC.

Dans certains langages de programmation, vous pouvez combiner les types Union et les types Intersection dans la même déclaration. Mais PHP 8.1 l’interdit. C’est pourquoi sa mise en œuvre est appelée types d’intersection « purs ». Cependant, la RFC mentionne que c’est « laissé comme une scope future »

Enums

PHP 8.1 ajoute enfin la prise en charge des enums (également appelés énumérations ou types énumérés). Il s’agit d’un type de données défini par l’utilisateur, composé d’un ensemble de valeurs possibles.

L’exemple d’énumération le plus courant dans les langages de programmation est le type booléen, avec true et false comme deux valeurs possibles. C’est tellement courant qu’il est intégré dans de nombreux langages de programmation modernes.

Conformément à la RFC, les énumérations en PHP seront limitées aux « énumérations d’unités » au départ :

La portée de cette RFC est limitée 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 fantaisiste pour une constante primitive, et qui n’incluent pas d’informations associées supplémentaires. Cette capacité offre une prise en charge considérablement élargie pour la modélisation des données, les définitions de types personnalisées et le comportement de style monade. Les Enums permettent la technique de modélisation consistant à « rendre les états non valides irreprésentables », ce qui conduit à un code plus robuste nécessitant moins de tests exhaustifs.

Pour arriver à ce stade, l’équipe PHP a étudié de nombreux langages qui prennent déjà en charge les énumérations. Leur étude a révélé que l’on peut classer les énumérations en trois groupes généraux : Constantes fantaisistes, objets fantaisistes et types de données algébriques (ADT) complets. C’est une lecture intéressante !

PHP implémente les énumérations « Fancy Objects », et prévoit de les étendre aux ADT complets à l’avenir. Il est conceptuellement et sémantiquement modelé sur les types énumérés de Swift, Rust et Kotlin, bien qu’il ne soit pas directement modelé sur aucun d’entre eux.

La RFC utilise la célèbre analogie des couleurs dans un jeu de cartes pour expliquer son fonctionnement :

enum Suit {
case Hearts;
case Diamonds;
case Clubs;
case Spades;

Ici, l’enum Suit définit quatre valeurs possibles : Hearts, Diamonds, Clubs et Spades. Vous pouvez accéder directement à ces valeurs en utilisant la syntaxe : Suit::Hearts, Suit::Diamonds, Suit::Clubs, et Suit::Spades.

Cette utilisation peut vous sembler familière, car les enums sont construits au-dessus des classes et des objets. Ils se comportent de manière similaire et ont presque les mêmes exigences. Les enums partagent les mêmes espaces de noms que les classes, les interfaces et les traits.

Les enums mentionnés ci-dessus sont appelés Pure Enums.

Vous pouvez aussi définir des Enums Backed si vous voulez donner une valeur scalaire équivalente à n’importe quel cas. Cependant, les backed enums ne peuvent avoir qu’un seul type, soit int soit string (jamais les deux).

enum Suit: string {
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}

De plus, tous les différents cas d’un backed enum doivent avoir une valeur unique. Et vous ne pouvez jamais mélanger les enums purs et backed.

La RFC approfondit les méthodes d’énumération, les méthodes statiques, les constantes, les expressions constantes et bien plus encore. Les couvrir tous dépasse le cadre de cet article. Vous pouvez vous référer à la documentation pour vous familiariser avec toutes ses qualités.

Le type de retour never

PHP 8.1 ajoute un nouvel indice de type de retour appelé never. C’est très utile pour les fonctions throw ou exit.

Selon la RFC, les fonctions de redirection d’URL exit (explicitement ou implicitement) sont un bon exemple de son utilisation :

function redirect(string $uri) : never {
    header('Location : ' . $uri) ;
    exit() ;
}
 
fonction redirectToLoginPage() : never {
    redirect('/login');
}

Une fonction déclarée never doit satisfaire trois conditions :

  • L’instruction return ne doit pas être définie explicitement.
  • L’instruction return ne doit pas être définie implicitement (par exemple, les instructions if-else).
  • Elle doit terminer son exécution avec une déclaration exit (explicitement ou implicitement).

L’exemple de redirection d’URL ci-dessus montre une utilisation à la fois explicite et implicite du type de retour never.

Le type never return partage de nombreuses similitudes avec le type void return. Ils garantissent tous deux que la fonction ou la méthode ne renvoie pas de valeur. Cependant, il diffère en appliquant des règles plus strictes. Par exemple, une fonction déclarée void peut toujours return sans valeur explicite, mais vous ne pouvez pas faire la même chose avec une fonction déclarée never.

En règle générale, utilisez void lorsque vous voulez que PHP continue à s’exécuter après l’appel de la fonction. Choisissez never lorsque vous voulez le contraire.

De plus, never est défini comme un type « inférieur ». Par conséquent, toute méthode de classe déclarée never ne peut « jamais » changer son type de retour en quelque chose d’autre. Cependant, vous pouvez étendre une méthode déclarée void avec une méthode déclarée never.

Fibers

Historiquement, le code PHP a presque toujours été un code synchrone. L’exécution du code s’arrête jusqu’à ce que le résultat soit renvoyé, même pour les opérations d’E/S. Vous pouvez imaginer pourquoi ce processus peut rendre l’exécution du code plus lente.

Il existe de multiples solutions tierces pour surmonter cet obstacle et permettre aux développeurs d’écrire du code PHP de manière asynchrone, notamment pour les opérations d’E/S simultanées. Parmi les exemples populaires, on trouve amphp, ReactPHP et Guzzle.

Cependant, il n’y a pas de moyen standard de gérer de telles instances en PHP. De plus, traiter le code synchrone et asynchrone dans la même pile d’appels entraîne d’autres problèmes.

Les fibers sont la façon dont PHP gère le parallélisme via les threads virtuels (ou threads verts). Elle cherche à éliminer la différence entre le code synchrone et asynchrone en permettant aux fonctions PHP de s’interrompre sans affecter l’ensemble de la pile d’appels.

Voici ce que promet la RFC:

  • Ajout de la prise en charge des fibers à PHP.
  • Introduction d’une nouvelle classe Fiber et de la classe de réflexion correspondante ReflectionFiber.
  • Ajout des classes d’exception FiberError et FiberExit pour représenter les erreurs.
  • Les fibers permettent des implémentations d’E/S non bloquantes transparentes des interfaces existantes (PSR-7, Doctrine ORM, etc.). C’est parce que l’objet placeholder (promesse) est éliminé. À la place, les fonctions peuvent déclarer le type de résultat E/S au lieu d’un objet placeholder qui ne peut pas spécifier de type de résolution car PHP ne prend pas en charge les génériques.

Vous pouvez utiliser Fibers pour développer des fonctions PHP interruptibles sur toute la pile d’exécution, que vous pouvez ensuite utiliser pour mettre en œuvre le multitâche coopératif en PHP. Comme fibers interrompt toute la pile d’exécution, vous pouvez être tranquille en sachant que cela ne nuira pas au reste de votre code.

Graphique illustrant le flux d'exécution du code PHP avec Fibers
Graphique illustrant le flux d’exécution du code PHP avec Fibers (Source : PHP.net).

Pour illustrer l’utilisation de Fibers, son RFC utilise cet exemple simple :

$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('fiber');
    echo "Value used to resume fiber: ", $value, "\n";
});
 
$value = $fiber->start();
 
echo "Value from fiber suspending: ", $value, "\n";
 
$fiber->resume('test');

Vous créez un « fiber » dans le code ci-dessus et vous la suspendez immédiatement avec la chaîne fiber. L’instruction echo sert de repère visuel pour la reprise de fiber.

Vous pouvez récupérer la valeur de cette chaîne de caractères à partir de l’appel à $fiber->start().

Ensuite, vous reprennez fiber avec la chaîne « test », qui est renvoyée par l’appel à Fiber::suspend(). L’exécution complète du code donne une sortie qui se lit comme suit :

Value from fiber suspending: fiber
Value used to resume fiber: test

C’est l’exemple de base de PHP Fibers au travail. Voici un autre exemple de Fibers qui consiste à effectuer sept requêtes GET asynchrones.

Tout étant dit et fait, la plupart des développeurs PHP n’auront jamais affaire à Fibers directement. Et la RFC suggère même la même chose :

Les fibers sont une fonctionnalité avancée que la plupart des utilisateurs n’utiliseront pas directement. Cette fonctionnalité s’adresse principalement aux auteurs de bibliothèques et de frameworks pour fournir une boucle d’événements et une API de programmation asynchrone. Les fibers permettent d’intégrer l’exécution de code asynchrone de façon transparente dans le code synchrone à n’importe quel endroit sans avoir à modifier la pile d’appels de l’application ou à ajouter du code passe-partout.

L’API Fiber n’est pas censée être utilisée directement dans le code au niveau de l’application. Les Fibers fournissent une API de contrôle de flux de base et de bas niveau pour créer des abstractions de plus haut niveau qui sont ensuite utilisées dans le code de l’application.

Compte tenu de ses avantages en termes de performances, vous pouvez vous attendre à ce que les bibliothèques et les frameworks PHP tirent parti de cette nouvelle fonctionnalité. Il sera intéressant de voir comment ils implémentent Fibers dans leur écosystème.

Nouvelles propriétés readonly

PHP 8.1 ajoute la prise en charge des propriétés readonly. Elles ne peuvent être initialisées qu’une seule fois à partir du scope où elles sont déclarées. Une fois initialisées, vous ne pouvez jamais modifier leur valeur. Si vous le faisiez, vous déclencheriez une exception Error.

Sa RFC est la suivante :

readonly ne peut être initialisée qu’une seule fois, et uniquement à partir du scope où elle a été déclarée. Toute autre affectation ou modification de la propriété entraînera une exception d’erreur.

Voici un exemple de la façon dont vous pouvez l’utiliser :

class Test {
    public readonly string $kinsta;
 
    public function __construct(string $kinsta) {
        // Legal initialization.
        $this->kinsta = $kinsta;
    }
}

Une fois initialisée, il n’y a pas de retour en arrière possible. Le fait que cette fonctionnalité soit intégrée à PHP réduit considérablement le code passe-partout qui est souvent utilisé pour activer cette fonctionnalité.

La propriété readonly offre une solide garantie d’immuabilité, tant à l’intérieur qu’à l’extérieur de la classe. Le code exécuté entre les deux n’a aucune importance. L’appel d’une propriété readonly renverra toujours la même valeur.

Cependant, l’utilisation de la propriété readonly peut ne pas être idéale dans certains cas d’utilisation spécifiques. Par exemple, vous ne pouvez les utiliser qu’à côté d’une propriété typée, car les déclarations sans type sont implicitement null et ne peuvent pas être readonly.

En outre, définir une propriété readonly ne rend pas les objets immuables. La propriété readonly conservera le même objet, mais cet objet lui-même peut changer.

Un autre problème mineur avec cette propriété est que vous ne pouvez pas la cloner. Il existe déjà une solution de contournement pour ce cas d’utilisation particulier. Cherchez-la si nécessaire.

Définir des constantes de classe final

Depuis PHP 8.0, vous pouvez remplacer les constantes de classe par ses classes filles. Cela est dû à la façon dont l’héritage est implémenté en PHP.

Voici un exemple de la façon dont vous pouvez remplacer la valeur d’une constante précédemment déclarée :

class Moo
{
    public const M = "moo";
}
 
class Meow extends Moo
{
    public const M = "meow";
}  

Maintenant, si les vaches veulent être plus strictes avec le comportement des chats (au moins avec les constantes), elles peuvent le faire avec le nouveau modificateur final de PHP 8.1.

Une fois que vous avez déclaré une constante comme étant final, cela signifie que.

class Moo
{
    final public const M = "moo";
}
 
class Meow extends Moo
{
    public const M = "meow";
}
 
// Fatal error: Meow::M cannot override final constant Moo::M

Vous pouvez en savoir plus à ce sujet dans la RFC PHP sur les constantes de classe finales.

Nouvelles fonctions fsync() et fdatasync()

PHP 8.1 ajoute deux nouvelles fonctions de système de fichiers appelées fsync() et fdatasync(). Elles sembleront familières à ceux qui sont habitués aux fonctions Linux du même nom. C’est parce qu’elles sont apparentées, simplement implémentées pour PHP.

En fait, cet ajout s’est fait attendre depuis longtemps. PHP est l’un des rares langages de programmation majeurs qui n’a toujours pas implémenté fsync() et fdatasync(), c’est-à-dire jusqu’à PHP 8.1.

La fonction fsync() est similaire à la fonction fflush() existante de PHP, mais elle diffère considérablement sur un point. Alors que fflush() vide les tampons internes de l’application dans le système d’exploitation, fsync() va plus loin et s’assure que les tampons internes sont vidés dans le stockage physique. Cela garantit une écriture complète et persistante afin que vous puissiez récupérer les données même après une panne de l’application ou du système.

Voici un exemple de la façon dont vous pouvez l’utiliser.

$doc = 'kinsta.txt';

$kin = fopen($doc, 'ki');
fwrite($kin, 'info doc');
fwrite($kin, '\r\n');
fwrite($kin, 'more info');

fsync($kin);
fclose($kin);

L’ajout de l’appel fsync() à la fin garantit que toutes les données contenues dans le tampon interne de PHP ou du système d’exploitation sont écrites dans le stockage. Toutes les autres exécutions de code sont bloquées jusqu’à ce moment-là.

Sa fonction apparentée est fdatasync(). Utilisez-la pour synchroniser les données mais pas nécessairement les métadonnées. Pour les données dont les métadonnées ne sont pas essentielles, cet appel de fonction rend le processus d’écriture un peu plus rapide.

Cependant, vous devez savoir que PHP 8.1 ne prend pas encore totalement en charge fdatasync() sous Windows. Elle agit simplement comme un alias de fsync(). Sous POSIX, fdatasync() est correctement implémenté.

Nouvelle fonction array_is_list()

Les tableaux PHP peuvent contenir à la fois des clés entières et des chaînes de caractères. Cela signifie que vous pouvez les utiliser pour plusieurs choses, notamment des listes, des tables de hachage, des dictionnaires, des collections, des piles, des files d’attente et bien plus encore. Vous pouvez même avoir des tableaux dans des tableaux, créant ainsi des tableaux multidimensionnels.

Vous pouvez vérifier efficacement si une entrée particulière est un tableau, mais il n’est pas si facile de vérifier s’il manque des offsets de tableau, si les clés ne sont pas dans l’ordre, etc. En bref, vous ne pouvez pas vérifier rapidement si un tableau est une liste.

La fonction array_is_list() vérifie si les clés d’un tableau sont en ordre séquentiel à partir de 0, et sans aucun vide. Si toutes les conditions sont remplies, elle renvoie true. Par défaut, elle renvoie également true pour les tableaux vides.

Voici quelques exemples d’utilisation de la fonction avec des conditions true et false remplies :

// true array_is_list() examples
array_is_list([]); // true
array_is_list([1, 2, 3]); // true
array_is_list(['cats', 2, 3]); // true
array_is_list(['cats', 'dogs']); // true
array_is_list([0 => 'cats', 'dogs']); // true
array_is_list([0 => 'cats', 1 => 'dogs']); // true 

// false array_is_list() examples 
array_is_list([1 => 'cats', 'dogs']); // as first key isn't 0
array_is_list([1 => 'cats', 0 => 'dogs']); // keys are out of order
array_is_list([0 => 'cats', 'bark' => 'dogs']); // non-integer keys
array_is_list([0 => 'cats', 2 => 'dogs']); // gap in between keys 

Une liste de tableaux PHP dont les clés ne sont pas dans l’ordre est une source potentielle de bogues. Utiliser cette fonction pour imposer un respect strict des exigences de la liste avant de passer à l’exécution du code est un excellent ajout à PHP.

Nouvelles fonctions Sodium XChaCha20

Sodium est une bibliothèque cryptographique moderne et facile à utiliser pour le cryptage, le décryptage, le hachage de mots de passe, les signatures et bien plus encore. Le paquet PECL libsodium ajoute un wrapper pour Sodium afin que les développeurs PHP puissent l’utiliser.

Même les grandes entreprises technologiques comme Facebook, Discord, Malwarebytes et Valve utilisent libsodium pour sécuriser leurs utilisateurs avec des connexions rapides et sûres.

libsodium prend en charge l’algorithme de cryptage XChaCha20 pour crypter et décrypter les données, notamment pour le cryptage des flux. De même, l’extension libsodium de PECL prend déjà en charge XChaCha20, mais uniquement avec le code d’authentification des messages Poly1305.

De nombreuses applications PHP utilisent directement XChaCha20 pour le chiffrement des flux. Pour faciliter les choses, à partir de PHP 8.1, vous aurez trois nouvelles fonctions pour crypter ou décrypter des données avec XChaCha20 sans que l’authentification soit impliquée. Ce mode est appelé « mode détaché »

Les fonctions XChaCha20 nouvellement introduites sont :

  • sodium_crypto_stream_xchacha20_keygen: Renvoie une clé aléatoire sécurisée à utiliser avec sodium_crypto_stream_xchacha20.
  • sodium_crypto_stream_xchacha20: Développe la clé et le nonce en un flux de clés d’octets pseudo-aléatoires.
  • sodium_crypto_stream_xchacha20_xor: Chiffre un message en utilisant un nonce et une clé secrète (pas d’authentification).

De plus, il y a deux nouvelles constantes PHP définies dans l’espace de noms global :

  • SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES (assigné 32)
  • SODIUM_CRYPTO_STREAM_XCHACHA20_NONCEBYTES (assigné 24)

Utilisez-le cependant avec prudence. Puisqu’il n’y a pas d’authentification, l’opération de décryptage est vulnérable aux attaques courantes par texte chiffré.

Vous pouvez en savoir plus sur son utilisation et ses exigences sur la page GitHub.

Nouvelle classe IntlDatePatternGenerator

La bibliothèque ICU sous-jacente de PHP prend en charge la création de formats de date et d’heure localisés, mais elle n’est pas entièrement personnalisable.

Par exemple, si vous voulez créer des formats de données et d’heure spécifiques à une région jusqu’à PHP 8.0, vous pouvez utiliser la constante prédéfinie IntlDateFormatter pour le faire de 6 façons :

  • IntlDateFormatter::LONG: Plus long, comme 10 novembre 2017 ou 11:22:33pm
  • IntlDateFormatter::MEDIUM: Un peu plus court, comme Nov 10, 2017
  • IntlDateFormatter::SHORT: Juste numérique, comme 10/11/17 ou 11:22pm

Chacune d’entre elles possède également ses propres variantes RELATIVE_, qui définissent le formatage de la date dans une plage limitée avant ou après la date actuelle. En PHP, les valeurs sont yesterday, today et tomorrow.

Disons que vous voulez utiliser la version longue pour l’année et la version courte pour le mois, comme 10/11/2017. Depuis PHP 8.0, vous ne pouvez pas.

Dans PHP 8.1+, vous pouvez spécifier les formats à utiliser pour la date, le mois et l’heure avec la nouvelle classe IntlDatePatternGenerator. Vous pouvez laisser l’ordre exact de ces composants au formateur.

Vous devez noter que même si cette classe ne contient que le mot Date, elle est cohérente avec le DateTimePatternGenerator d’ICU. Cela signifie que vous pouvez aussi l’utiliser pour créer des formats d’heure flexibles. Pour simplifier l’attribution des noms, l’équipe PHP a choisi d’utiliser le terme plus court IntlDatePatternGenerator.

Voici un exemple tiré directement de sa RFC:

$skeleton = "YYYYMMdd";
 
$today = \DateTimeImmutable::createFromFormat('Y-m-d', '2021-04-24');
 
$dtpg = new \IntlDatePatternGenerator("de_DE");
$pattern = $dtpg->getBestPattern($skeleton);
echo "de: ", \IntlDateFormatter::formatObject($today, $pattern, "de_DE"), "\n";
 
$dtpg = new \IntlDatePatternGenerator("en_US");
$pattern = $dtpg->getBestPattern($skeleton), "\n";
echo "en: ", \IntlDateFormatter::formatObject($today, $pattern, "en_US"), "\n";
 
/*
de: 24.04.2021
en: 04/24/2021
*/

Dans le code ci-dessus, la variable skeleton définit les formats de date ou d’heure particuliers à utiliser. Cependant, le formateur gère l’ordre du résultat final.

Prise en charge du format d’image AVIF

AVIF, ou AV1 Image File Format, est un format d’image libre de droits relativement nouveau basé sur le format de codage vidéo AV1. Outre le fait qu’il offre une compression plus élevée (et donc des tailles de fichiers plus petites), il prend également en charge plusieurs fonctionnalités telles que la transparence, le HDR, et plus encore.

Le format AVIF n’a été normalisé que récemment (8 juin 2021). Cela a ouvert la voie aux navigateurs, tels que Chrome 85+ et Firefox 86+, qui ajoutent la prise en charge des images AVIF.

L’extension GD et de traitement des images de PHP 8.1 ajoute la prise en charge des images AVIF.

Cependant, pour inclure cette fonctionnalité, vous devez compiler l’extension GD avec la prise en charge d’AVIF. Vous pouvez le faire en exécutant les commandes ci-dessous.

Pour Debian/Ubuntu :

apt install libavif-dev

Pour Fedora/RHEL :

dnf install libavif-devel

Cela permettra d’installer toutes les dernières dépendances. Ensuite, vous pouvez compiler le support AVIF en exécutant le flag --with-avif avec le script ./configure.

./buildconf --force
./configure --enable-gd --with-avif

Si vous démarrez un nouvel environnement à partir de zéro, vous pouvez aussi activer d’autres extensions PHP ici.

Une fois installé, vous pouvez tester si la prise en charge d’AVIF est activée en exécutant la commande suivante dans votre terminal PHP :

php -i | grep AVIF

Si vous avez installé AVIF correctement, vous verrez le résultat suivant :

Support AVIF => enabled

Vous pouvez aussi utiliser l’appel gd_info() pour récupérer une liste des fonctionnalités de GD, y compris si la fonctionnalité de soutien AVIF est activée.

Cette extension GD PHP 8.1 mise à jour ajoute également deux nouvelles fonctions pour travailler avec les images AVIF : imagecreatefromavif et imageavif. Elles fonctionnent de manière similaire à leurs homologues JPEG et PNG.

La fonction imagecreatefromavif renvoie une instance GdImage à partir d’une image AVIF donnée. Vous pouvez ensuite utiliser cette instance pour modifier ou convertir l’image.

L’autre fonction imageavif produit le fichier image AVIF. Par exemple, vous pouvez l’utiliser pour convertir un JPEG en AVIF :

$image = imagecreatefromjpeg('image.jpeg');
imageavif($image, 'image.avif');

Vous pouvez en savoir plus sur cette nouvelle fonction sur sa page GitHub.

Nouvelle clé $_FILES : full_path pour les téléversements de répertoires

PHP gère un grand nombre de variables prédéfinies pour suivre diverses choses. L’une d’entre elles est la variable $_FILES qui contient un tableau associatif d’éléments téléversés via la méthode HTTP POST.

La plupart des navigateurs modernes prennent en charge le téléversement d’un répertoire entier avec les champs de téléversement de fichiers HTML. Même PHP <8.1 prenait en charge cette fonctionnalité, mais avec une grosse réserve. Vous ne pouviez pas téléverser un répertoire avec sa structure de répertoire exacte ou ses chemins relatifs car PHP ne transmettait pas ces informations au tableau $_FILES.

Cela change dans PHP 8.1 avec l’ajout d’une nouvelle clé nommée full_path au tableau $_FILES. Grâce à ces nouvelles données, vous pouvez stocker des chemins relatifs ou dupliquer la structure exacte du répertoire sur le serveur.

Vous pouvez tester ces informations en sortant le tableau $FILES à l’aide de la commande var_dump($_FILES) ;.

Cependant, faites preuve de prudence si vous utilisez cette fonctionnalité. Assurez-vous de vous protéger contre les attaques standard de téléversement de fichiers.

Prise en charge du déballage des tableaux pour les tableaux à clé de caractères

PHP 7.4 a ajouté la prise en charge du déballage des tableaux avec l’opérateur d’étalement de tableau (). Il s’agit d’une alternative plus rapide à l’utilisation de la fonction array_merge(). Cependant, cette fonctionnalité était limitée aux tableaux à clés numériques car le déballage des tableaux à clés de type chaîne provoquait des conflits lors de la fusion des tableaux avec des clés dupliquées.

Cependant, PHP 8 a ajouté la prise en charge des arguments nommés, supprimant ainsi cette limitation. Par conséquent, le déballage de tableaux prend désormais en charge les tableaux à clé de type chaîne de caractères en utilisant la même syntaxe :

$array = [...$array1, ...$array2];

Cet exemple de RFC illustre comment la fusion de tableaux avec des clés de chaîne dupliquées est gérée en PHP 8.1 :

$array1 = ["a" => 1];
$array2 = ["a" => 2];
$array = ["a" => 0, ...$array1, ...$array2];
var_dump($array) ; // ["a" => 2]

Ici, la clé de chaîne « a » apparaît trois fois avant la fusion via le déballage du tableau. Mais seule sa dernière valeur appartenant à $array2 est gagnante.

Notation numérique octale explicite

PHP prend en charge différents systèmes numériques, notamment décimal (base-10), binaire (base-2), octal (base-8) et hex (base-16). Le système numérique décimal est le système par défaut.

Si vous voulez utiliser un autre système numéral, vous devrez préfixer chaque nombre avec un préfixe standard :

  • Hex : Préfixe 0x. (par exemple, 17 = 0x11)
  • Binaire : Préfixe 0b. (par exemple, 3 = 0b11)
  • Octal : Préfixe 0. (par ex. 9 = 011)

Vous pouvez voir comment le préfixe du système numéral octal diffère des autres. Pour normaliser cette préoccupation, de nombreux langages de programmation ajoutent la prise en charge d’une notation numérale octale explicite : 0o ou 0O.

À partir de PHP 8.1, vous pouvez écrire l’exemple ci-dessus (c’est-à-dire le nombre 9 en base 10) dans le système numérique octal sous la forme 0o11 ou 0O11.

0o16 === 14; // true
0o123 === 83; // true
 
0O16 === 14; // true
0O123 === 83; // true
 
016 === 0o16; // true
016 === 0O16; // true

De plus, cette nouvelle fonctionnalité fonctionne également avec le séparateur numérique littéral underscore introduit dans PHP 7.4.

Pour en savoir plus sur cette nouvelle fonctionnalité de PHP 8.1, consultez sa RFC.

Prise en charge des algorithmes de hachage MurmurHash3 et xxHash

PHP 8.1 ajoute la prise en charge des algorithmes de hachage MurmurHash3 et xxHash. Ils ne sont pas conçus pour une utilisation cryptographique, mais ils offrent tout de même un caractère aléatoire, une dispersion et une unicité de sortie impressionnants.

Ces nouveaux algorithmes de hachage sont plus rapides que la plupart des algorithmes de hachage existants de PHP. En fait, certaines variantes de ces algorithmes de hachage sont plus rapides que le débit de la RAM.

Comme PHP 8.1 ajoute également la prise en charge de la déclaration de paramètres $options spécifiques aux algorithmes, vous pouvez faire de même avec ces nouveaux algorithmes. La valeur par défaut de ce nouvel argument est []. Ainsi, cela n’affectera aucune de nos fonctions de hachage existantes.

Vous pouvez en savoir plus sur ces nouvelles fonctionnalités de PHP 8.1 sur leurs pages GitHub : MurmurHash3, xxHash, $options spécifiques aux algorithmes.

Prise en charge de DNS-over-HTTPS (DoH)

DNS-over-HTTPS (DoH) est un protocole pour la résolution DNS via le protocole HTTPS. En utilisant HTTPS pour chiffrer les données entre le client et le résolveur DNS, DoH augmente la confidentialité et la sécurité des utilisateurs en empêchant les attaques MitM.

À partir de PHP 8.1, vous pouvez utiliser l’extension Curl pour spécifier un serveur DoH. Elle nécessite que PHP soit compilé avec les versions libcurl 7.62+. Ce n’est pas un problème pour la plupart des systèmes d’exploitation populaires, y compris les distributions Linux, car elles incluent souvent Curl 7.68+.

Vous pouvez configurer l’URL du serveur DoH en spécifiant l’option CURLOPT_DOH_URL.

$doh = curl_init('https://kinsta.com');
curl_setopt($doh, CURLOPT_DOH_URL, 'https://dns.google/dns-query');
curl_exec($doh);

Dans l’exemple ci-dessus, nous avons utilisé le serveur DNS public de Google. Remarquez également l’utilisation de https:// dans toutes les URL utilisées. Assurez-vous de configurer cela parfaitement car il n’y a pas de serveur DNS par défaut auquel se rabattre dans Curl.

Vous pouvez aussi choisir parmi une liste de serveurs DoH publics inclus dans la documentation de Curl.

De plus, la référence CURLOPT_DOH_URL de la documentation Curl explique en détail comment utiliser ses différents arguments.

Téléversements de fichiers à partir de chaînes de caractères avec CURLStringFile

L’extension PHP Curl prend en charge les requêtes HTTP(S) avec des téléversements de fichiers. Elle utilise pour cela la classe CURLFile, qui accepte un URI ou un chemin d’accès à un fichier, un type mime et le nom final du fichier.

Cependant, avec la classe CURLFile, vous ne pouvez accepter que le chemin d’accès au fichier ou l’URI, mais pas le contenu du fichier lui-même. Dans les cas où vous aviez déjà le fichier à téléverser en mémoire (par exemple, des images traitées, des documents XML, des PDF), vous deviez utiliser des URI data:// avec un encodage Base64.

Mais libcurl prend déjà en charge un moyen plus simple d’accepter le contenu du fichier. La nouvelle classe CURLStringFile ajoute un support pour cela précisément.

Vous pouvez lire sa page GitHub pour en savoir plus sur la façon dont elle est implémentée dans PHP 8.1.

Nouvelle constante MYSQLI_REFRESH_REPLICA

L’extension mysqli de PHP 8.1 ajoute une nouvelle constante appelée MYSQLI_REFRESH_REPLICA. Elle est équivalente à la constante existante MYSQLI_REFRESH_SLAVE.

Ce changement était le bienvenu dans MySQL 8.0.23 pour remédier à l’insensibilité raciale dans le vocabulaire technique (les exemples les plus courants incluent « esclave » et « maître »).

Vous devez noter que l’ancienne constante n’est pas supprimée ou dépréciée. Les développeurs et les applications peuvent continuer à l’utiliser. Cette nouvelle constante n’est qu’une option pour les développeurs et les entreprises qui souhaitent laisser de côté cette terminologie.

Amélioration des performances avec Inheritance Cache

Inheritance Cache est un nouvel ajout à opcache qui élimine la surcharge de l’héritage des classes PHP.

Les classes PHP sont compilées et mises en cache par opcache séparément. Cependant, elles sont déjà liées au moment de l’exécution sur chaque requête. Ce processus peut impliquer plusieurs contrôles de compatibilité et l’emprunt de méthodes/propriétés/constantes des classes et traits parents.

Par conséquent, l’exécution de ce processus prend un temps considérable, même si le résultat est le même pour chaque requête.

Inheritance Cache relie toutes les classes dépendantes uniques (parents, interfaces, traits, types de propriétés, méthodes) et stocke les résultats dans la mémoire partagée d’opcache. Comme cela ne se produit qu’une fois, l’héritage nécessite moins d’instructions.

De plus, il supprime les limitations des classes immuables, comme les constantes non résolues, les propriétés typées et les contrôles de type covariants. Ainsi, toutes les classes stockées dans opcache sont immuables, ce qui réduit encore le nombre d’instructions nécessaires.

Au final, cela promet des avantages significatifs en termes de performances. Dimitry Stogov, l’auteur de ce patch, a constaté qu’il présentait une amélioration de 8 % sur le programme de base de Symfony « Hello, World ! ». Nous sommes impatients de le tester dans nos prochains benchmarks PHP.

Syntaxe d’appel de première classe

PHP 8.1 ajoute une syntaxe d’appel de première classe pour remplacer les codages existants utilisant des chaînes et des tableaux. En plus de créer un Closure plus propre, cette nouvelle syntaxe est également accessible par les outils d’analyse statique et respecte la portée déclarée.

Voici quelques exemples tirés de la RFC:

$fn = Closure::fromCallable('strlen');
$fn = strlen(...);
 
$fn = Closure::fromCallable([$this, 'method']);
$fn = $this->method(...)
 
$fn = Closure::fromCallable([Foo::class, 'method']);
$fn = Foo::method(...);

Ici, toutes les paires d’expressions sont équivalentes. La syntaxe à triple point (... ) est similaire à la syntaxe de déballage des arguments (...$args). Sauf qu’ici, les arguments ne sont pas encore remplis.

Changements dans PHP 8.1

PHP 8.1 comprend également des modifications de sa syntaxe et de ses fonctionnalités existantes. Discutons-en :

Le shell interactif de PHP nécessite l’extension readline

L’extension readline de PHP permet d’utiliser les fonctions du shell interactif telles que la navigation, l’autocomplétion, l’édition, etc. Bien qu’elle soit fournie avec PHP, elle n’est pas activée par défaut.

Vous pouvez accéder au shell interactif de PHP en utilisant l’option de ligne de commande -a de PHP CLI :

php -a

Interactive shell

php >
php > echo "Hello";
Hello
php > function test() {
php { echo "Hello";
php { }
php > test();
Hello

Avant PHP 8.1, vous pouviez ouvrir le shell interactif à l’aide de PHP CLI même si l’extension readline n’était pas activée. Comme prévu, les fonctions interactives du shell ne fonctionnaient pas, ce qui rendait l’option -a inutile.

Dans PHP 8.1 CLI, le shell interactif se termine par un message d’erreur si vous n’avez pas activé l’extension readline.

php -a
Interactive shell (-a) requires the readline extension.

Le mode d’erreur par défaut de MySQLi est défini sur Exceptions

Avant PHP 8.1, MySQLi affichait par défaut les erreurs en mode silencieux. Ce comportement conduisait souvent à un code qui ne suivait pas une gestion stricte des erreurs/exceptions. Les développeurs devaient implémenter leurs propres fonctions explicites de gestion des erreurs.

PHP 8.1 change ce comportement en définissant le mode de signalement des erreurs par défaut de MySQLi pour lancer une exception.

Fatal error: Uncaught mysqli_sql_exception: Connection refused in ...:...

Comme il s’agit d’un changement de rupture, pour les versions PHP <8.1, vous devez définir explicitement le mode de traitement des erreurs à l’aide de la fonction mysqli_report avant d’établir la première connexion MySQLi. Vous pouvez aussi faire de même en sélectionnant la valeur de signalement des erreurs en instanciant une instance de mysqli_driver.

La RFC suit un changement similaire introduit dans PHP 8.0.

Fin de ligne personnalisable pour les fonctions d’écriture CSV

Avant PHP 8.1, les fonctions d’écriture CSV intégrées de PHP, fputcsv et SplFileObject::fputcsv, étaient codées en dur pour ajouter un \n (ou le caractère Line-Feed) à la fin de chaque ligne.

PHP 8.1 ajoute la prise en charge d’un nouveau paramètre nommé eol à ces fonctions. Vous pouvez l’utiliser pour passer un caractère de fin de ligne configurable. Par défaut, il utilise toujours le caractère \n. Vous pouvez donc continuer à l’utiliser dans votre code existant.

Les règles standard d’échappement des caractères s’appliquent à l’utilisation des caractères de fin de ligne. Si vous voulez utiliser \r, \n, ou \r\n comme caractères de fin de ligne, vous devez les mettre entre guillemets.

Voici la page GitHub qui suit cette nouvelle modification.

Nouvelles restrictions de l’opérateur version_compare

La fonction version_compare() de PHP compare deux chaînes de numéros de version. Cette fonction accepte un troisième argument facultatif appelé operator pour tester une relation particulière.

Bien que cela ne soit pas explicitement mentionné dans la documentation, avant PHP 8.1, vous pouviez définir ce paramètre sur une valeur partielle (par exemple g, l, n) sans risquer une erreur.

PHP 8.1 ajoute des restrictions plus strictes à l’argument operator de la fonction version_compare() pour pallier cette situation. Les seuls opérateurs que vous pouvez désormais utiliser sont :

  • ==, =, et eq
  • !=, <>, et ne
  • > et gt
  • >= et ge
  • < et lt
  • <= et le

Plus de valeurs partielles d’opérateur.

Les fonctions d’encodage et de décodage HTML utilisent désormais ENT_QUOTES | ENT_SUBSTITUTE

Les entités HTML sont des représentations textuelles de caractères qui seraient autrement interprétés comme du HTML. Pensez aux caractères tels que < et > utilisés pour définir les balises HTML (par exemple <a>, <h3>, <script>).

L’entité HTML pour < est & lt; (moins que le symbole) et > est & gt; (plus que le symbole).

Note : Enlevez l’espace entre « & » et « amp ».

Vous pouvez utiliser ces entités HTML en toute sécurité dans un document HTML sans déclencher le moteur de rendu du navigateur.

Par exemple, & lt;script& gt; s’affichera comme <script> dans le navigateur, plutôt que d’être interprété comme une balise HTML.

Avant PHP 8.1, les fonctions htmlspecialchars() et htmlentities() convertissaient les symboles comme « , <, >, et & en leurs entités HTML respectives. Mais elles ne convertissaient pas le caractère guillemet simple (') en son entité HTML par défaut. De plus, elles renvoyaient une chaîne vide s’il y avait un UTF-8 malformé dans le texte.

En PHP 8.1., ces fonctions d’encodage et de décodage HTML (et leurs fonctions connexes) convertiront également les caractères guillemets simples en leur entité HTML par défaut.

Et si le texte donné contient des caractères non valides, les fonctions les remplaceront par un caractère de substitution Unicode (�) au lieu de renvoyer une chaîne vide. PHP 8.1 accomplit cela en changeant les signatures de ces fonctions en ENT_QUOTES | ENT_SUBSTITUTE plutôt qu’en ENT_COMPAT par défaut.

La plupart des frameworks utilisent déjà ENT_QUOTES comme valeur par défaut de l’indicateur. Vous ne verrez donc pas beaucoup de différence suite à ce changement. Cependant, le nouveau drapeau ENT_SUBSTITUTE n’est pas très utilisé. PHP 8.1 fera en sorte que les caractères UTF-8 invalides soient remplacés par le caractère � au lieu de renvoyer une chaîne vide.

Avertissement sur les appels illégaux à la fonction compact

La fonction compact() de PHP est super pratique. Vous pouvez l’utiliser pour créer un tableau avec des variables en utilisant leurs noms et leurs valeurs.

Par exemple, considèrez le code suivant :

$animal = 'Cat';
$sound = 'Meow';
$region = 'Istanbul';
compact('animal', 'sound', 'region');
// ['animal' => "Cat", 'sound' => "Meow", 'region' => "Istanbul"]

La documentation de la fonction compact indique qu’elle n’accepte que les paramètres de type chaîne ou les valeurs de tableau avec des valeurs de type chaîne. Cependant, avant PHP 7.3, toutes les chaînes qui ne sont pas définies sont ignorées en silence.

PHP 7.3 a modifié la fonction compact() pour afficher un avis si vous utilisez des variables indéfinies. PHP 8.1 va encore plus loin et affiche un avertissement.

Vous pouvez lire sa page GitHub pour comprendre comment ce changement est apparu.

Nouvelles migrations des ressources vers les objets de classe

L’un des objectifs à long terme de PHP est de passer des ressources aux objets de classe standard.

Pour des raisons historiques, les objets ressources sont largement utilisés dans les applications PHP. Par conséquent, la migration des ressources vers les objets de classe doit être aussi peu perturbante que possible. PHP 8.1 fait migrer cinq de ces ressources :

La ressource file_info migrée vers les objets finfo

La classe finfo de PHP offre une interface orientée objet pour les fonctions fileinfo. Cependant, l’utilisation des fonctions finfo renvoie des objets ressources avec le type file_info plutôt qu’une instance de la classe finfo elle-même.

PHP 8.1 corrige cette anomalie.

Les ressources IMAP ont migré vers les objets de la classe IMAP\Connection

Conformément à l’objectif de migration des ressources vers les objets, la nouvelle classe IMAP\Connection minimise les changements de rupture potentiels lorsque PHP modifie éventuellement les détails de l’implémentation de la classe.

Cette nouvelle classe est également déclarée finale, vous n’êtes donc pas autorisé à extend.

Lisez-en plus sur sa mise en œuvre sur sa page GitHub.

Les ressources de connexion FTP sont maintenant des objets de la classe FTP\Connection

En PHP <8.1, si vous créiez une connexion FTP avec les fonctions ftp_connect() ou ftp_ssl_connect(), vous récupériez un objet ressource de type ftp.

PHP 8.1 ajoute la nouvelle classe FTP\Connection pour rectifier cela. Et comme pour la classe IMAP\Connection, elle est également déclarée finale pour éviter qu’elle ne soit étendue.

Lisez-en plus sur sa mise en œuvre sur sa page GitHub.

Les identificateurs de police ont migré vers les objets de la classe GdFont

L’extension GD de PHP fournit la fonction imageloadfont() pour charger un bitmap défini par l’utilisateur et renvoyer son identifiant de ressource de police (un nombre entier).

En PHP 8.1, cette fonction renverra plutôt une instance de la classe GdFont. De plus, pour faciliter la migration, toutes les fonctions qui acceptaient auparavant un ID de ressource de imageloadfont() prendront désormais les nouveaux objets de la classe GdFont.

Pour en savoir plus sur cette migration, consultez sa page GitHub.

Les ressources LDAP ont migré vers des objets

LDAP, ou Lightweight Directory Access Protocol, est utilisé pour accéder aux « serveurs de répertoire » Comme une structure de répertoire de disque dur, c’est une base de données unique qui contient des données dans une structure arborescente.

PHP inclut une extension LDAP qui acceptait ou renvoyait des objets resource avant PHP 8.1. Cependant, ils ont tous migré de façon transparente vers de nouvelles instances de classe maintenant. Les types de ressources qui ont fait l’objet d’une transition sont :

  • ressource ldap link vers l’objet de classe \LDAP\Connection
  • ressource ldap result vers l’objet de classe \LDAP\Result
  • ressource ldap result entry vers l’objet de classe \LDAP\ResultEntry

Consultez sa page GitHub pour mieux comprendre cette migration.

Les ressources Pspell sont maintenant des objets de classe

L’extension Pspell de PHP vous permet de vérifier l’orthographe et les suggestions de mots.

PHP <8.1 utilisait les types d’objets ressources pspell et pspell config avec un identifiant entier. Ces deux objets ressources sont désormais remplacés par les objets de classe PSpell\Dictionary et PSpell\Config.

Comme pour les migrations précédentes, toutes les fonctions Pspell qui acceptaient ou renvoyaient auparavant des identifiants d’objets ressources prendront les nouvelles instances d’objets de classe.

Reportez-vous à sa page GitHub pour plus d’informations.

Dépréciations dans PHP 8.1

PHP 8.1 rend obsolète un grand nombre de ses fonctionnalités précédentes. La liste suivante donne un bref aperçu des fonctionnalités que PHP 8.1 déprécie :

Impossible de passer null à des paramètres de fonction non nuls

Depuis PHP 8.0, ses fonctions internes acceptent silencieusement les valeurs null même pour les arguments non nuls. Il n’en va pas de même pour les fonctions définies par l’utilisateur : elles n’acceptent null que pour les arguments nullables.

Par exemple, considère cette utilisation :

var_dump(str_contains("foobar", null));
// bool(true)

Ici, la valeur nul est silencieusement convertie en une chaîne vide. Ainsi, le résultat renvoie true.

Cette RFC vise à synchroniser le comportement des fonctions internes en lançant un avertissement de dépréciation dans PHP 8.1.

var_dump(str_contains("foobar", null));
// Deprecated: Passing null to argument of type string is deprecated

La dépréciation deviendra une TypeError dans la prochaine version majeure de PHP (c’est-à-dire PHP >=9.0), rendant le comportement des fonctions internes cohérent avec les fonctions définies par l’utilisateur.

Utilisation restreinte de $GLOBALS

La variable $GLOBALS de PHP fournit une référence directe à sa table de symboles interne. La prise en charge de cette fonctionnalité est complexe et affecte les performances des opérations de tableau. De plus, elle est rarement utilisée.

Conformément à la RFC, la modification indirecte de $GLOBALS n’est plus autorisée. Ce changement est incompatible avec le passé.

L’impact de ce changement est relativement faible :

Dans les 2000 premiers paquets du composer, j’ai trouvé 23 cas qui utilisent $GLOBALS sans le déréférencer directement. D’après une inspection sommaire, il n’y a que deux cas où $GLOBALS n’est pas utilisé en lecture seule.

Cependant, l’utilisation en lecture seule de $GLOBALS continue de fonctionner comme d’habitude. Ce qui n’est plus pris en charge, c’est l’écriture dans $GLOBALS dans son ensemble. Par conséquent, vous pouvez vous attendre à une légère augmentation des performances, surtout lorsque vous travaillez avec des tableaux PHP ordinaires.

Déclarations de type de retour pour les fonctions internes

PHP 8.0 a permis aux développeurs de déclarer les paramètres et les types de retour pour la plupart des fonctions et méthodes internes. Cela a été possible grâce à diverses RFC telles que Consistent type errors for internal functions, Union Types 2.0, et Mixed Type v2.

Cependant, il existe de nombreux cas où les informations de type peuvent manquer. Certains d’entre eux incluent un type avec des ressources, des paramètres out pass-by-ref, le type de retour des méthodes non finales, et les fonctions ou méthodes qui n’analysent pas les paramètres selon les règles générales. Vous pouvez lire les détails exacts dans sa RFC.

Cette RFC ne traite que le problème du type de retour des méthodes non finales. Cependant, plutôt que de l’éliminer complètement et immédiatement, l’équipe PHP propose une voie de migration progressive pour mettre à jour vos bases de code avec les types de retour des méthodes concernées.

Les types de retour des méthodes internes non finales – lorsque cela est possible – sont déclarés provisoirement dans PHP 8.1, et ils seront appliqués dans PHP 9.0. Cela signifie que dans les versions PHP 8.x, un avis « déprécié» est affiché pendant les vérifications d’héritage lorsqu’une méthode interne est surchargée d’une manière qui rend les types de retour incompatibles, et PHP 9.0 en fera une erreur fatale.

Si vous voyez cette notification de dépréciation après avoir mis à jour PHP 8.1, assurez-vous de mettre à jour les types de retour de vos méthodes.

Interface sérialisable dépréciée

PHP 7.4 a introduit le mécanisme de sérialisation des objets personnalisés avec deux nouvelles méthodes magiques : __serialize() et __unserialize(). Ces nouvelles méthodes ont pour but de remplacer à terme l’interface Serializable qui n’existe plus.

Cette RFC propose de finaliser cette décision en établissant un plan pour la suppression éventuelle de Serializable.

Dans PHP 8.1, si vous implémentez l’interface Serializable sans implémenter les méthodes __serialize() et __unserialize(), PHP lancera un avertissement « Deprecated ».

Deprecated: The Serializable interface is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in ... on line ...

Si vous supportez PHP <7.4 et PHP >=7.4, vous devez implémenter à la fois l’interface Serializable et les nouvelles méthodes magiques. Sur les versions PHP >=7.4, les méthodes magiques seront prioritaires.

Conversions non compatibles de float à int dépréciées

PHP est un langage dynamiquement typé. En tant que tel, il existe de nombreux cas où la coercition de type se produit naturellement. La plupart de ces coercitions sont inoffensives et super pratiques.

Cependant, lorsqu’un nombre flot est converti en integer, cela entraîne souvent une perte de données. Par exemple, lorsque le nombre flottant 3,14 est converti en un nombre entier 3, il perd sa valeur fractionnaire.

La même chose se produit lorsque le float est en dehors de la plage d’entiers de la plateforme, ou lorsqu’une chaîne de floats est convertie en entier.

PHP 8.1 rectifie ce comportement et aligne sa contrainte de type dynamique sur la plupart des langages de programmation modernes. L’objectif est de rendre ces coercitions prévisibles et intuitives.

Dans PHP 8.1, vous verrez un avis de dépréciation lorsqu’un float non compatible est implicitement converti en int. Mais qu’est-ce qui constitue un float compatible avec les entiers ? La RFC répond à cette question :

Un float est dit compatible avec les entiers s’il possède les caractéristiques suivantes :

  • Est un nombre (c’est-à-dire pas NaN ou Infinity)
  • Est dans la plage d’un entier PHP (selon la plateforme)
  • N’a pas de partie fractionnaire

Cet avis de dépréciation sera transformé en TypeError dans la prochaine version majeure de PHP (c’est-à-dire PHP 9.0).

Les méthodes mysqli::get_client_info et mysqli_get_client_info($param) sont dépréciées

L’API client MySQL définit deux constantes : client_info (une chaîne) et client_version (un int). MySQL Native Driver (MySQLnd) fait partie de la source officielle de PHP et associe ces constantes à la version de PHP. Dans libmysql, elles représentent la version de la bibliothèque client au moment de la compilation.

Avant PHP 8.1, mysqli exposait ces constantes de 4 façons : propriétés mysqli_driver, propriétés mysqli, fonction mysqli_get_client_info() et méthode mysqli::get_client_info. Cependant, il n’y a pas de méthode pour client_version.

MySQLnd expose ces constantes de 2 façons à PHP : une constante et un appel de fonction. Pour unifier les méthodes d’accès mysqli avec ces deux mêmes options, PHP 8.1 déprécie ces deux autres options :

  • la méthode get_client_info de la classe mysqli. À la place, vous pouvez simplement utiliser la fonction mysqli_get_client_info().
  • fonction mysqli_get_client_info() avec paramètres. Appelle la fonction sans aucun paramètre pour éviter l’avis de dépréciation.

Lisez-en plus sur cette dépréciation sur sa page GitHub.

Toutes les fonctions mhash*() (extension hash) sont dépcréciées

PHP 5.3 a intégré les fonctions mhash*() dans ext/hash comme couche de compatibilité pour ext/mhash. Plus tard, PHP 7.0 a supprimé ext/mhash.

Contrairement aux fonctions hash_*(), les fonctions mhash*() ne sont pas toujours disponibles. Vousdevez les activer séparément lors de la configuration de PHP.

Dans PHP 7.4, l’extension hash a été fournie avec PHP, ce qui en fait une extension par défaut pour PHP. Cependant, l’activation de l’option --enable-mhash est toujours possible pour des raisons de compatibilité.

L’équipe PHP a décidé de déprécier les fonctions mhash*() dans PHP 8.1, et de les supprimer complètement dans PHP 9.0. Les fonctions dépréciées sont mhash(), mhash_keygen_s2k(), mhash_count(), mhash_get_block_size() et mhash_get_hash_name(). Vous pouvez utiliser les fonctionnalités standard de ext/hash à leur place.

Les paramètres INI filter.default et filter.default_options sont dépréciés

Les paramètres INI filter.default de PHP vous permettent d’appliquer un filtre à tous les super-globaux de PHP, c’est-à-dire aux données GPCRS ($_GET, $_POST, $_COOKIE, $_REQUEST et $_SERVER).

Par exemple, vous pouvez définir filter.default=magic_quotes ou filter.default=add_slashes (en fonction de la version de PHP) pour ressusciter la fonction controversée et peu sûre des guillemets magiques de PHP (supprimée dans PHP 5.4).

Le paramètre INI filter.default fournit une fonctionnalité supplémentaire en autorisant beaucoup plus de filtres, ce qui rend la situation encore pire. Par exemple, son autre option – filter.default=special_chars – active les guillemets magiques uniquement pour le HTML. Ces paramètres sont beaucoup moins connus.

PHP 8.1 lancera un avertissement de dépréciation si filter.default est défini sur une valeur autre que unsafe_raw (la valeur par défaut). Vous ne verrez pas d’avis de dépréciation distinct pour filter.default_options, mais PHP 9.0 supprimera ces deux paramètres INI.

Comme alternative, vous pouvez commencer à utiliser la fonction filter_var(). Elle filtre les variables avec le filtre spécifié.

Déprécier l’autovivification sur false

PHP permet l’autovivification (création automatique de tableaux à partir de valeurs fausses). Cette fonction est super utile si la variable est indéfinie.

Néanmoins, il n’est pas idéal de créer automatiquement un tableau lorsque la valeur est fausse ou nulle.

Ce RFC interdit l’autovivification à partir de valeurs fausses. Cependant, notez que l’autovivification à partir de variables indéfinies et de null est toujours autorisée.

En PHP 8.1, l’ajout à une variable de type false émettra un avis de dépréciation :

Deprecated: Automatic conversion of false to array is deprecated in

PHP 9.0 lancera une erreur fatale pour la même chose, ce qui est identique aux autres types scalaires.

La propriété mysqli_driver->driver_version est dépréciée

La propriété mysqli_driver->driver_version de l’extension MySQLi n’a pas été mise à jour depuis 13 ans. Malgré les nombreuses modifications apportées au pilote depuis lors, il renvoie toujours l’ancienne valeur de la version du pilote, ce qui rend cette propriété inutile.

Dans PHP 8.1, la propriété mysqli_driver->driver_version est dépréciée.

Autres changements mineurs

Il y a beaucoup plus de dépréciations dans PHP 8.1. Les lister toutes ici serait un exercice épuisant. Nous vous recommandons de consulter directement le RFC pour ces dépréciations mineures.4

La page GitHub de PHP comprend également un guide des NOTES DE MISE À JOUR de PHP 8.1. Il répertorie tous les changements de rupture que vous dois prendre en compte avant de passer à PHP 8.1.

Résumé

PHP 8.1 est meilleur que son prédécesseur, ce qui n’est pas une mince affaire. Nous pensons que les fonctionnalités les plus intéressantes de PHP 8.1 sont les Enums, les Fibers, les Pure Intersection Types, et ses nombreuses améliorations de performances. De plus, nous sommes impatients de mettre PHP 8.1 à l’épreuve et de comparer différents frameworks et CMS PHP.

N’oubliez pas d’ajouter cet article de blog dans vos favoris pour vous y référer ultérieurement.

Quelle fonctionnalité de PHP 8.1 est votre préférée ? Partagez vos pensées avec la communauté dans la section des commentaires ci-dessous.

Salman Ravoof

Salman Ravoof is a self-taught web developer, writer, creator, and a huge admirer of Free and Open Source Software (FOSS). Besides tech, he's excited by science, philosophy, photography, arts, cats, and food. Learn more about him on his website, and connect with Salman on Twitter.