Prendre Rendez-vous
Logo Olympe Studio blanc

PHP 8.3 est Disponible ! Découverte des nouvelles fonctionnalités

La version 8.3 de PHP est sortie le jeudi 23 Novembre 2023. Elle comporte son lot de nouveauté, mais globalement, ce n’est pas un patch aussi intéressant que le précédent.

Cette version apporte un rafraîchissement du langage, visant à harmoniser certaines fonctionnalités avec les évolutions récentes de PHP.

Elle apporte en confort de développement et rend certaines choses plus simples ou plus logiques à l’aide de nouvelles fonctions.

Faisons un tour exhaustif des nouveautés avec des exemples pratiques. (et compréhensibles)

Sommaire

Nouvelle fonction json_validate()

Cette fonction permet de vérifier explicitement qu’une chaîne de caractère contient du JSON valide.

Son introduction permet de gérer plus facilement les chaînes JSON récupérées dynamiquement et de les traiter de manière plus lisible. Elle rend le code plus lisible et moins sujet à l’introduction de bogues.

Voici un exemple simple et concret de son usage :

<?php

$validJsonData = '{"name": "John", "age": 30}';
// Il manque une guillemet après "age"
$invalidJsonData = '{"name": "John", "age: 30}';

// > Pass - Valid JSON
if (json_validate($validJsonData)) {
    echo "Pass - Valid JSON";
} else {
    echo "Fail - Invalid JSON";
}

// > Fail- Invalid JSON
if (json_validate($invalidJsonData)) {
    echo "Pass - Valid JSON";
} else {
    echo "Fail - Invalid JSON";
}

Comme vous pouvez le remarquer, c’est une façon de faire plutôt simple et logique. On est bien loin de l’ancienne approche qui nécessitait des appels de fonction un peu étranges.

Voici comme nous faisions ce même travail avant :

<?php

$jsonData = '{"name": "John", "age": 30}';

// Decode the JSON string
$data = json_decode($jsonData);

// Check for errors in decoding
if (json_last_error() === JSON_ERROR_NONE) {
    echo "Valid JSON";
} else {
    echo "Invalid JSON";
}

Bien que ça soit relativement compréhensible aussi, on est bien loin de la facilité et de la lisibilité de la nouvelle approche. Cette méthode est la bienvenue !

Fallback pour les anciennes versions

Si comme nous, vous êtes tenté de l’utiliser dans vos librairies, vous allez devoir implémenter une fallback, dans le cas où la version de PHP utilisée par le projet ne soit pas la 8.3. (ce qui est très probable)

Voici comment faire :

<?php
// Chargez ce fichier PHP avant tous les autres.
// Pas de namespace, cette fonction doit appartenir à la racine.

if (!function_exists('json_validate')) {
    /**
     * Fallback for json_validate function in PHP < 8.3.
     *
     * @param string $json JSON string to validate.
     *
     * @return bool True if the JSON string is valid, false otherwise.
     */
    function json_validate($json, int $depth = 512, int $flag = 0) {
        json_decode($json, $depth, $flag);
        return json_last_error() === JSON_ERROR_NONE;
    }
}

Maintenant, vous pouvez utiliser cette fonction d’ores et déjà dans vos projets. Bien entendu, elle sera moins performante que la fonction innée.

Son rôle, c’est d’assurer la rétrocompatibilité pour vous apporter du confort, pas d’être plus performante !

L’attribut (ou décorateur) #[\Override]

Cet attribut permet dans une classe enfant d’indiquer qu’une méthode va overrider la méthode parente.

Attention. Cet attribut va s’assurer que la méthode à overrider existe bel et bien dans la classe parente. Si ce n’est pas le cas, vous aurez une erreur.

À première vue, ça peut paraître étrange.

Cette fonctionnalité répond à deux nécessités :

  • Éviter d’introduire un bug de typographie difficile à identifier : Si vous faites une faute de frappe, vous serez ramené à l’erreur lancée par l’attribut.
  • Éviter les régressions lorsque vous allez faire évoluer le code. Si vous changez la méthode dans le parent, ou l’enfant, vous serez ramené à l’erreur lancé par l’attribut.

C’est donc un outil intéressant pour construire du code plus portable.

La Programmation orientée objet, surtout si vous êtes débutant, peut rapidement s’avérer être un enfer absolu. La mise en place de ce genre de « rappel » est très pratique, surtout si vous travaillez en équipe ou que vos développeurs sont amenés à changer.

Voici un exemple pratique de l’utilisation de ce décorateur :

<?php

class NotificationSender {
    public function send($message) {
        // Logic for sending a basic notification
        echo "Sending notification: $message";
    }
}

class EmailNotificationSender extends NotificationSender {
    #[\Override]
    public function send($message) {
        // Override to send notification via email
        echo "Sending email notification: $message";
    }
}

// Usage
$notification = new EmailNotificationSender();
$notification->send("Hello World!");

Maintenant, si jamais je modifie la méthode send, dans l’une des deux classes, j’obtiendrais une erreur à l’exécution.

Ainsi, si j’avais 40 {NomduSender}NotificationSender héritant de NotificationSender, je serais certain de ne pas pouvoir pousser du code en production en ayant oublié de corriger la comptabilité partout.

Nouvelles Méthodes pour \Random\Randomizer

La classe Randomizer introduite avec PHP 8.2 bénéficie de 3 nouvelles méthodes avec PHP 8.3.

Ces fonctions permettent de créer de manière bien plus simple des éléments récurrents de manière aléatoire.

Voici les nouvelles méthodes disponibles.

getBytesFromString()

Cette fonction permet de générer une chaîne d’octets aléatoires à partir d’une chaîne de caractère de départ.

Elle est particulièrement utile pour créer des chaînes aléatoires telles que des tokens, des mots de passe ou n’importe quels autres identifiants pour lesquels vous avez besoin de caractères spécifiques.

Voici un exemple pratique :

<?php

$randomizer = new \Random\Randomizer();
$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

// Génère un mot de passe de 10 characters.
$password = $randomizer->getBytesFromString($characters, 10);

echo $password;

Dans cet exemple, le mot de passe n’utilisera que les caractères disponibles dans la chaine passée en premier argument, ce qui rend cette fonction très pratique pour limiter l’usage de certains caractères.

Le second paramètre, quant à lui, indique la longueur de la sortie.

Elle peut-être plus longue que la chaîne de départ, ça n’a pas d’importance.

getFloat()

PHP 8.3 introduit deux nouvelles méthodes afin de créer des valeurs décimales aléatoires.

La première est la méthode getFloat, qui prend deux paramètres :

  • Le premier est la valeur minimale possible,
  • Le second, la valeur maximale.

Ainsi, si vous utilisez la fonction comme cela :

<?php

$randomizer = new \Random\Randomizer();

$randomFloatA = $randomizer->getFloat(0, 1);
echo "Random float between 0 and 1: $randomFloatA";

$randomFloatB = $randomizer->getFloat(-5, 5);
echo "Random float between -5 and 5: $randomFloatB";

Par défaut, la valeur min peut être renvoyée, mais pas la valeur max. Pour modifier ce comportement, vous pouvez utiliser l’enum \Random\IntervalBoundary.

Je trouve personnellement que c’est assez peu lisible, mais voici les valeurs possibles :

  • IntervalBoundary::ClosedOpen (valeur par défaut): la valeur min peut être renvoyée, mais pas la valeur max
  • IntervalBoundary::ClosedClosed : les valeurs min et max sont toutes les deux inclusives. (elles peuvent être renvoyées toutes les deux)
  • IntervalBoundary::OpenClosed : min ne peut pas être retourné, max peut l’être
  • IntervalBoundary::OpenOpen : les valeurs min et max sont toutes les deux exclusives. (ni min ni max ne peuvent être renvoyés).

Voici un exemple pour illustrer l’usage de ce paramètre :

<?php

// Crée une température aléatoire.
$randomizer = new Random\Randomizer();
$temperature = $randomizer->getFloat(-10, 40, \Random\IntervalBoundary::ClosedClosed);

// La température pourra être -10, ainsi que 40.
echo "Simulated Temperature: " . $temperature . "°C";

nextFloat()

La méthode nextFloat() est une méthode sans paramètre qui permet de générer une valeur décimale entre 0 et 1 (avec \Random\IntervalBoundary::ClosedOpen).

Le retour peut donc être 0, mais n’atteindra jamais 1.

Le nom de cette méthode est atroce, je ne vous recommande pas de l’utiliser. Il est beaucoup plus lisible et compréhensible d’utiliser getFloat(0, 1);

Constantes des classes

Les constantes de classes ont bénéficié de changements mineurs, mais tout de même intéressant. Il est maintenant possible de les typer, et de les appeler dynamiquement. Voici comment ça se présente.

Type des constantes de classes

Avec PHP 8.3, il est maintenant possible d’assigner un type à une constante de classe, d’interface ou de trait.

Si vous aimez comme nous typer l’intégralité de votre application, c’est un ajout intéressant !

Voici un exemple pratique :

<?php

interface Application {
    // Type déclaré et valeur sont tous les deux des chaînes de caractères
    const string SOFTWARE_NAME = "Olympe_Studio_App";
    // fonctionne également
    const int RELEASE_YEAR = 2024;

    // This will throw an error.
    const bool IS_IN_PRODUCTION = "yes";
}

Attention cependant.

Les types void et never ne sont pas supportés comme type valide pour les constantes de classe.

C’est assez logique puisque, à quoi bon créer une constante avec ces types ? Mais bon, sachez-le. Ce n’est pas possible.

Appel dynamique des constantes de class et membres d’une Enum.

Avec ce patch, il est maintenant possible d’appeler une constante ou un élément d’une Enum en utilisant son nom stocké dans une variable.

avant, avec PHP < 8.3, il fallait faire appel à la fonction constant($className::, $contantName).

Maintenant, vous pouvez améliorer la lisibilité de votre code.

<?php

// Class avec des constantes
class Vehicle {
    const MAX_SPEED = 200;
    const MIN_SPEED = 0;
}

// enum pour les couleurs des véhicules
enum Color: string {
    const RED = '#FF0000';
    const BLUE = '#0000FF';
    const GREEN = '#00FF00'; 
}

$vehicleAttribute = 'MAX_SPEED'; // Nom de l'attribut du véhicule
$colorChoice = 'Blue';           // Choix de la couleur

// Accès dynamique en PHP >= 8.3
echo Vehicle::{$vehicleAttribute};  // Accès à la vitesse maximale de Vehicle
echo Color::{$colorChoice}->value;  // Accès à la couleur Bleu


// Avant, il fallait faire :
echo constant('Vehicle::' . $vehicleAttribute);
echo constant('Color::' . $colorChoice)->value;

Il ne s’agit globalement que d’une amélioration de la lisibilité, mais c’est tout à fait bienvenu.

Clonage des propriétés readonly

PHP 8.1 a introduit la possibilité de marquer des propriétés spécifiques de classe comme étant en lecture seule (readonly).

Après, avec PHP 8.2, cette fonctionnalité a été étendue, permettant l’attribution de l’attribut readonly à une classe complète.

Néanmoins, les restrictions associées à l’utilisation de classes avec de telles propriétés limitaient grandement la flexibilité de programmation dans le cas du clonage :

  • Immutabilité stricte après l’initialisation,
  • Sérialisation et désérialisation complexe,
  • Tests et Mockup.
  • etc.

Pour remédier à cela, PHP 8.3 permet aux propriétés readonly d’être réinitialisées au moment du clonage, en s’appuyant sur la méthode magique __clone.

<?php

readonly class BlogArticle {
    public function __construct(
        public string $title,
        public string $author,
        public DateTime $createdAt,
    ) {}

    // Méthode magique __clone pour le clonage de l'objet
    public function __clone() {
        // Lors du clonage, on réinitialise `createdAt` à la date et heure actuelles.
        $this->createdAt = new DateTime(); 
    }
}

$post = new BlogArticle('Titre de l\'article', 'Auteur', new DateTime('2023-01-01'));
$clonedPost = clone $post;

// Le clone aura la date et heure actuelles pour `createdAt`
echo $clonePost->createdAt->format('Y-m-d H:i:s');

Conclusion

PHP 8.3 apporte des améliorations subtiles, mais importantes, améliorant la flexibilité et la lisibilité du langage.

Les nouveautés sont certes mineures, mais enrichissent l’expérience développeur et la flexibilité pour les programmes complexes et les librairies.

Bien que PHP 8.3 ne soit pas une révolution, il continue de moderniser et d’affiner le langage, bénéficiant ainsi aux développeurs PHP dans la création de code plus propre et efficace.

Sources :

Annonce officielle de PHP 8.3
Téléchargement

Toutes les autres versions de PHP

Découvrez nos autres articles sur les mises à jour de PHP.

– PHP 8.1
– PHP 8.2
– PHP 8.4 (en cours de développement)