Il y a de l’épice de citrouille dans l’air, il est donc temps de lancer une nouvelle version de PHP, le langage de script côté serveur qui fait fonctionner notre CMS préféré, WordPress. Avant le lancement de la version 8.4 le 21 novembre, les développeurs de PHP ont dévoilé de nombreuses versions préliminaires de la nouvelle base de code, y compris une poignée de versions candidates depuis le gel des fonctionnalités en août.

En plus des nouvelles fonctionnalités, des améliorations et des dépréciations, nous anticipons cette période de l’année, 2024 a vu des ajustements au cycle de publication de PHP, avec la fin des versions de sécurité pour toutes les versions actuellement prises en charge synchronisées à la fin de l’année au lieu de son anniversaire GA.

De plus, ce support a été prolongé d’un an, ce qui signifie que vous pourriez utiliser PHP 8.4 en toute sécurité jusqu’en 2028 (avec deux ans de sécurité et de corrections de bogues et deux ans de corrections de sécurité uniquement).

Bien que vous puissiez passer plus de temps avec PHP 8.4, vous avez probablement envie de découvrir dès maintenant les nouveautés de cette version. Alors, sautons dans le vif du sujet.

Nouvelles fonctionnalités et améliorations de PHP 8.4

Les nouvelles fonctionnalités incluses dans la version 8.3 de PHP l’année dernière vous sembleront discrètes par rapport à certains des ajouts de la version 8.4 :

Hooks de propriété

Les hooks de propriété apportent une toute nouvelle approche de la gestion des « getters » et des « setters » dans la programmation orientée objet (POO) de PHP, te permettant de simplifier la structure de vos fichiers de classe.

Pour illustrer ce que les hooks de propriété peuvent remplacer, la classe simple ci-dessous comprend les propriétés $size et $flavor. Elles ont une visibilité de private pour les protéger d’un accès direct en dehors de l’objet résultant. C’est pourquoi les méthodes publiques getter et setter servent de médiateur pour l’accès aux propriétés :

class Coffee
{
    private string $size;
    private string $flavor;
    public function __construct(string $size, string $flavor) {
        $this->size   = $size;
        $this->flavor = $flavor;
    }

    // "Setting" coffee size and flavor
    public function setSize(string $size): void {
        $this->size = $size;
    }
    public function setFlavor(string $flavor): void {
        $this->flavor = $flavor;
    }

    // "Getting" coffee size and flavor
    public function getSize(): string {
        return $this->size;
    }
    public function getFlavor(): string {
        return $this->flavor;
    }
} // End of class

// Make some coffee
$coffee = new Coffee('Small', 'Pumpkin Spice');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Small Pumpkin Spice"

// Change order
$coffee->setSize('Grande');
$coffee->setFlavor('Mocha');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Grande Mocha"

Ou alors, votre classe a beaucoup de propriétés, et au lieu d’écrire de nombreuses méthodes getter et setter, vous utilisez les méthodes magiques de PHP _get et _set. Vous pourriez même régler les choses dans une déclaration switch quelque peu désordonnée, comme dans l’extrait ci-dessous.

// __set magic method example
public function __set(string $key, $value): void 
    switch ($key) {
        case 'size':
            $this->size = $value;
            break;
        case 'flavor':
            $this->flavor = $value;
            break;
        default:
            throw new InvalidArgumentException('Invalid input');
        }
}

// Later, we can change the coffee order like this:
$coffee->size = 'Grande';
$coffee->flavor = 'Mocha';

Quelle que soit l’approche que vous choisissiez, plus vous avez de propriétés dans votre classe, plus le code utilisé pour les manipuler sera éloigné de leurs définitions situées en haut de votre fichier de classe. De plus, certaines implémentations des méthodes magiques _get et _set peuvent inopinément donner accès à des propriétés privées ou protégées de votre objet que vous n’aviez pas l’intention d’exposer.

La nouvelle fonction de hooks de propriété regroupe les fonctionnalités d’obtention et de définition avec les propriétés elles-mêmes. Dans l’exemple de hooks de propriété ci-dessous, vous remarquerez que les propriétés $size et $flavor de la classe Coffee sont désormais publiques. Mais nous avons également ajouté une validation de base aux hooks set, pour les différencier des affectations directes.

// Property definitions at the top of our Coffee class
class Coffee
{
    public string $flavor {
        set(string $value) {
            if (strlen($value) > 16) throw new InvalidArgumentException('Input is too long');
                $this->flavor = $value;
        }
    }

    public string $size {
        set(string $value) {
            if (! in_array($value, array(‘Small’, ‘Grande’))) throw new InvalidArgumentException('Not a valid size');
                $this->size = $value;
        }
    }

    // Rest of the Coffee class
}

// Define a coffee
$coffee = new Coffee();
$coffee->size = 'Grande';
$coffee->flavor = 'Pumpkin spice';

De même, comme vous pouvez le voir ci-dessous, un hook get peut intégrer des fonctionnalités dans ce qui semble être une référence ordinaire à une propriété d’objet.

// Simplified Coffee class
class Coffee
{
    public string $flavor {
        get { 
            return $this->flavor . ' Spice';
       }
    }
}

// Create a flavor 
$coffee = new Coffee();
$coffee->flavor = 'Pumpkin'; // Stores the value "Pumpkin"
print $coffee->flavor;       // Prints "Pumpkin Spice"

Contrairement aux méthodes magiques de PHP, les hooks de propriété peuvent être utilisés dans les interfaces et les classes abstraites. Un exemple d’interface :

interface Coffee
{
    public string $size { get; set; }
    public string $flavor { get; set; }
}

Visibilité asymétrique

Les méthodes getter et setter publiquement visibles que nous avons examinées plus tôt représentent l’approche traditionnelle de l’accès aux propriétés privées et protégées au sein de leurs classes.

Une fonctionnalité intéressante de PHP 8.4 est la possibilité pour une propriété d’avoir différents niveaux de visibilité en fonction du contexte dans lequel elle est accédée. Ainsi, une propriété peut être publique lorsqu’elle est lue, mais privée ou protégée lorsqu’elle est définie.

Regardez ça :

class Coffee
{
    public private(set) string $flavor = 'Pumpkin Spice';
}

$coffee = new Coffee();
print $coffee->flavor;     // Prints "Pumpkin Spice"
$coffee->flavor = 'Mocha';  // Error (visibility)

Ci-dessus, la propriété $flavor de la classe est publique, sauf dans un contexte de définition. C’est déjà assez simple, mais la visibilité asymétrique a même un petit raccourci :

class Coffee
{
    // public is assumed when the context is not setting
    private(set) string $flavor = 'Pumpkin Spice';
}

Vous pouvez utiliser les hooks de propriété et la visibilité asymétrique en combinaison pour obtenir une énorme flexibilité dans le travail avec des propriétés d’objets de différentes visibilités.

Enchainer new sans parenthèses

En parlant de raccourcis, l’appel de new et l’enchainement de méthodes nécessitaient auparavant de placer l’invocation entre parenthèses, comme ceci :

$coffee = (new Coffee())->getFlavor()->getSize();

PHP 8.4 le permet :

$coffee = new Coffee()->getFlavor()->getSize();

Cela peut sembler être un changement mineur, mais le fait de laisser tomber seulement deux parenthèses rend cela beaucoup plus facile à lire et à déboguer.

Nouvelles fonctions pour trouver les éléments d’un tableau

Au rayon « Vous voulez dire qu’on ne pouvait pas déjà faire ça ? », PHP 8.4 introduit la fonction array_find(), qui permet de rechercher dans un tableau les éléments correspondant aux conditions exprimées dans une fonction de rappel. La fonction renvoie la valeur du premier élément correspondant au test de la fonction de rappel.

La nouvelle version comprend trois autres fonctions connexes :

  • array_find_key(): Comme array_find(), mais la valeur de retour est la clé de l’élément correspondant au lieu de la valeur de l’élément lui-même.
  • array_all(): Renvoie true si chaque élément du tableau testé correspond au test du rappel.
  • array_any(): Renvoie true si au moins un des éléments du tableau correspond au test de la fonction de rappel.

Notez que les deux dernières fonctions renvoient des indicateurs booléens au lieu des clés ou du contenu du tableau.

Voici quelques exemples rapides :

$array = [
    'a' => 'Mocha',
    'b' => 'Caramel',
    'c' => 'Maple',
    'd' => 'Pumpkin'
   ];

// Find the first flavor name that is 5 characters long
var_dump(array_find($array, function (string $value) {
    return strlen($value) == 5;
})); // Returns “Mocha,” even though “Maple” is the same length 

// Find the array key for the first flavor with a name longer than 5 characters.
var_dump(array_find_key($array, function (string $value) {
    return strlen($value) > 5;
})); // Returns “b”

// Check to see if any flavor name is less than 5 characters long
var_dump(array_any($array, function (string $value) {
    return strlen($value) < 5;
})); // Returns false

// Check to see if all flavor names are shorter than 8 characters
var_dump(array_all($array, function (string $value) {
    return strlen($value) < 8;
})); // Returns true

Analyse HTML5

HTM5 est la norme de facto pour la structure des pages web modernes, mais la technologie d’analyse du modèle d’objet de document (DOM) de PHP s’était arrêtée à HTML 4.01.

Plutôt que de mettre à jour la classe DOMDocument existante qui fonctionne avec les anciennes normes HTML, PHP 8.4 est livré avec une nouvelle classe DomHTMLDocument qui est prête pour le HTM5.

Vous pouvez importer le contenu d’une page HTML5 comme ceci :

$document = DomHTMLDocument::createFromString($html)

En plus du constructeur createFromString($html) ci-dessus, la classe supporte également createFromFile($path) et createEmpty()

Le nouvel analyseur reconnait les balises HTML5 sémantiques telles que main, article et section qui sont maintenant familières à la plupart d’entre nous.

Fonctions de découpage multi-octets

Un autre ajout de PHP 8.4 qui semble avoir été attendu depuis longtemps est la prise en charge de plusieurs octets dans les fonctions de découpage :

  • mb_trim()
  • mb_ltrim()
  • mb_rtrim()

Comme la fonction PHP trim() qui existe depuis longtemps, mb_trim supprime les espaces blancs et certains caractères spéciaux, comme les sauts de ligne, des deux extrémités d’une chaine qui peut contenir des caractères multi-octets. Les autres fonctions suppriment soit l’extrémité gauche, soit l’extrémité droite d’une chaine.

Dépréciations en PHP 8.4

Chaque version de PHP s’accompagne d’une liste de caractéristiques et de fonctions (certaines assez obscures) qui sont signalées comme devant être retirées de la plate-forme. L’une des dépréciations les plus médiatisées de PHP 8.4 est le suivi de session sans cookie.

Dépréciation des sessions GET/POST

Bien que les cookies soient généralement la méthode préférée pour suivre les sessions des utilisateurs, PHP a pris en charge la fixation des données d’identification de session dans les paramètres GET/POST. Pour permettre le suivi de session via des paramètres dans les URL, le paramètre PHP session.use_only_cookies est désactivé, et le paramètre session.use_trans_sid peut être activé.

Avec PHP 8.4, l’un ou l’autre de ces paramètres déclenche un avertissement de dépréciation qui peut apparaitre dans les journaux de votre site. Lorsque PHP 9 sera publié, ces paramètres ne seront plus disponibles.

Autres dépréciations (et suppressions) en PHP 8.4

Vous trouverezs ci-dessous une liste de fonctionnalités que l’équipe responsable de PHP 8.4 a décidé de supprimer. (Certaines incluent des liens vers plus d’informations sur les fonctionnalités…,

  • Dépréciation formelle des propriétés DOMDocument et DOMEntity.
  • Suppression de DOMImplementation::getFeature($feature, $version).
  • Déclassé la constante DOM_PHP_ERR.
  • Déclassé La balise « S » dans unserialize().
  • Dépréciation de session.sid_length et session.sid_bits_per_character.
  • Déclassement de SplFixedArray::__wakeup().
  • Déclasser xml_set_object() et xml_set_*_handler() avec les noms de méthodes en chaine.
  • Déclasser le passage de null et false à dba_key_split().
  • Déclasser le passage de types de données incorrects pour les options des fonctions ext/hash.
  • Déclasser les constantes SUNFUNCS_RET_STRING, SUNFUNCS_RET_DOUBLE, SUNFUNCS_RET_TIMESTAMP.
  • Suppression du mécanisme d’échappement CSV propriétaire.
  • Déclassement de la constante E_STRICT.
  • Déclasser strtok().
  • Déclasser le renvoi de valeurs autres que des chaines à partir d’un gestionnaire de sortie utilisateur.
  • Déclasser la production de sortie dans un gestionnaire de sortie utilisateur.
  • Déclasser file_put_contents() avec $data en tant que tableau.
  • Déprécier mysqli_ping() et mysqli::ping()
  • Déprécier mysqli_refresh().
  • Déprécier mysqli_kill().
  • Déclasser le deuxième paramètre de mysqli_store_result().
  • Déclasser lcg_value().
  • Déprécier uniqid().
  • Déprécier md5(), sha1(), md5_file()et sha1_file().
  • Déprécier le passage de E_USER_ERROR à trigger_error().
  • Déprécier l’utilisation d’un seul trait de soulignement (« _ ») comme nom de classe.
  • Déprécier la constante SOAP_FUNCTIONS_ALL et la passer à SoapServer::addFunction().

Résumé

PHP 8.4 apporte quelques changements intéressants. Nous sommes impatients d’installer cette version sur nos serveurs pour notre analyse comparative annuelle de PHP – nos tests avec divers systèmes de gestion de contenu basés sur PHP.

Nous sommes également impatients de voir quand les développeurs commenceront à intégrer certaines des nouvelles fonctionnalités de PHP 8.4 dans leurs projets, en particulier les hooks de propriété.

Quelles sont les fonctionnalités de PHP 8.4 que tu préfères ? Partagez vos idées avec notre communauté dans les commentaires !

Steve Bonisteel Kinsta

Steve Bonisteel est un rédacteur technique chez Kinsta qui a commencé sa carrière d'écrivain en tant que journaliste de presse écrite, chassant les ambulances et les camions de pompiers. Il couvre les technologies similaires à l'Internet depuis la fin des années 1990.