URL:     https://linuxfr.org/news/php-sort-en-version-8-2
Title:   PHP sort en version 8.2
Authors: windu.2b
        Ellendhel, vmagnin, bobble bubble, Pierre Jarillon, Yves Bourguignon, Nils Ratusznik et palm123
Date:    2022-04-29T15:48:53+02:00
License: CC By-SA
Tags:
Score:   3


Après 3 Alpha, 3 Beta et 7 RC, et tout juste un an après la sortie de [PHP 8.1](https://linuxfr.org/news/la-version-8-1-de-php-et-creation-de-la-fondation-php), PHP, le langage de programmation pour le Web le plus connu et le plus utilisé, sort ce jour [_attendre le 8 décembre 2022_, NdA] en version 8.2.
Petit tour (non-exhaustif) des nouveautés !

----


----

Nouvelles fonctionnalités
-----------


### Classes en lecture seule (_Readonly classes_ : [RFC](https://wiki.php.net/rfc/readonly_classes))

Après la possibilité offerte par PHP 8.1 d'ajouter le mot-clé _[readonly](https://wiki.php.net/rfc/readonly_properties_v2)_ aux propriétés d'une classe, c'est désormais directement sur la classe que l'on peut le faire.
Cela permet d'alléger le code, en évitant la répétition du même mot-clé sur chacune des propriétés d'une classe (au risque de l'oublier sur l'une d'entre elles, notamment lorsque le code vient à évoluer), et de le rendre plus clair (quand la classe est _readonly_, toutes ses propriétés le sont forcément).
Cela permet aussi d'empêcher la création de propriétés dynamiques (propriétés non déclarées dans le corps de la classe).
Le principal usage est bien évidemment les classes DTO (_Data Transfer Object_), en permettant d'instancier des objets garantis immuables.

On est donc passé de ceci, en PHP 8.0 :


```php
class Book
{
   /**
    * Constructeur PHP utilisant la nouvelle syntaxe "Constructor property promotion" apparue avec PHP 8.0
    * @see https://stitcher.io/blog/new-in-php-8#constructor-property-promotion-rfc
    */
   public function __construct(
       private string $title,
       private string $author;
   )
   {}

   public function getTitle(): string
   {
       return $this->title;
   }

   public function getAuthor(): string
   {
       return $this->author;
   }
}

$book = new Book('A Game of Thrones', 'George R.R. Martin');
$book->getAuthor(); // "George R.R. Martin"
```



Puis ça, en PHP 8.1 :


```php
class Book
{
   /**
    * Les propriétés étant déclarées 'readonly', elles peuvent être déclarées 'public' sans risque.
    */
   public function __construct(
       public readonly string $title,
       public readonly string $author,
   )
   {}

   // Suppression des getters, devenus inutiles
}

$book = new Book('A Game of Thrones', 'George R.R. Martin');

// On peut désormais appeler directement la propriété, sans craindre de la modifier
echo $book->author; // "George R.R. Martin"
$book->author = 'J.R.R. Tolkien'; // Error: Cannot modify readonly property Book::$author
```



Pour arriver finalement à ceci, en PHP 8.2 :


```php
// utilisation du mot-clé 'readonly' sur la classe directement
readonly class Book
{
   /**
    * La classe étant déclarée 'readonly', les propriétés peuvent être déclarées 'public' sans risque,
    * sans pour autant avoir encore besoin de les déclarer 'readonly' une à une.
    */
   public function __construct(
       public string $title,
       public string $author,
   )
   {}

   // Suppression des getters, devenus inutiles
}

$book = new Book('A Game of Thrones', 'George R.R. Martin');
echo $book->author; // "George R.R. Martin"
$book->author = 'J.R.R. Tolkien'; // Error: Cannot modify readonly property Book::$author
$book->genre = 'Epic fantasy'; // Uncaught Error: Cannot create dynamic property Book::$genre
```



**ATTENTION !**
Un objet _readonly_ n'est pas forcément immuable ! Si un objet A a une référence vers un objet B (composition), le fait que cette référence soit _readonly_ garantit uniquement que A ne pointera jamais vers C à la place de B. Mais cela n'empêche pas pour autant les propriétés de B de pouvoir changer dans le temps (si elles ne sont pas elles-mêmes _readonly_, évidemment).

### Dépréciation des propriétés dynamiques (_Deprecate dynamic properties_ : [RFC](https://wiki.php.net/rfc/deprecate_dynamic_properties))


Dans la continuité du refus d'ajouter une propriété dynamique sur une classe _readonly_, une Deprecated est désormais levée lorsqu'on fait appel à une propriété inexistante au sein de la classe/de l'objet.
Ex :

```php
class User {
   public $name;
}
$user = new User;

// Assigns declared property User::$name
$user->name = "foo";

// Oops, a typo:
$user->nane = "foo";
// PHP <= 8.1: Silently creates dynamic $user->nane property.
// PHP    8.2: "Deprecated: Creation of dynamic property User::$nane is deprecated"
// PHP    9.0: Throws Error exception.
```


Néanmoins, les cas où il faut pouvoir continuer à créer des propriétés dynamiques ont été pris en compte. Pour cela, 3 solutions :


#### Ajouter les méthodes magiques `__get` et/ou `__set` :

```php
class Post
{
   private array $properties = [];

   public function __set(string $name, mixed $value): void
   {
       $this->properties[$name] = $value;
   }

   // …
}

// …

$post->name = 'Name'; // Pas de message de dépréciation
```

#### Utiliser la classe `stdClass` de PHP (ou en hériter) :

```php
/*
* Ne faites pas ça : ça marche mais c'est une solution fortement déconseillée !
*/
class Post extends stdClass
{
}

$post = new Post();

$post->name = 'Name'; // Pas de message de dépréciation
```

#### Ajouter l'attribut `#[AllowDynamicProperties]` à la classe :


```php
/*
* Solution la plus recommandée pour gérer le code legacy, car l'impact est nul.
*/
#[AllowDynamicProperties]
class Post
{
}

$post = new Post();

$post->name = 'Name'; // Pas de message de dépréciation
```

À terme (PHP 9), le message passera de `Deprecated` à la levée d'une exception de type `Error`.

### Nouveaux types de retour : `null`, `true`, et `false` (_Allow null and false as stand-alone types_ : [RFC](https://wiki.php.net/rfc/null-false-standalone-types))

Il est désormais possible d'indiquer que le type de retour d'une fonction/méthode est `null`, `true`, ou `false`. C'est notamment utile pour les fonctions de PHP qui renvoient une valeur, ou `false` si un problème a été rencontré.
Par exemple :


```php
/*
* Trouve la première occurrence de $needle dans $haystack
* @return la portion de la chaîne, ou false si needle n'est pas trouvé.
*/
strstr(string $haystack, string $needle, bool $before_needle = false): string|false
```



### Masquage des données sensibles dans les logs (_Redacting parameters in back traces_ : [RFC](https://wiki.php.net/rfc/redact_parameters_in_back_traces))


Il est désormais possible d'indiquer que la valeur d'un paramètre ne doit jamais se retrouver dans des traces d'erreurs. C'est évidemment très utile pour éviter qu'un mot de passe ne finisse en clair dans un fichier de logs.
Pour cela, il faut ajouter un attribut à la variable concernée, comme ceci :



```php
function test(
   $foo = null,
   #[\SensitiveParameter] $bar = null,
   $baz = null
) {
   throw new \Exception('Error');
}
test(baz: 'baz');
/*
Fatal error: Uncaught Exception: Error in test.php:8
Stack trace:
#0 test.php(11): test(NULL, Object(SensitiveParameterValue), 'baz')
#1 {main}
 thrown in test.php on line 8
*/
```




Comme on le voit dans la trace d'erreur, la valeur du paramètre en entrée `$bar` a été remplacée par `Object(SensitiveParameterValue)`.


### Constantes dans les Traits ([RFC](https://wiki.php.net/rfc/constants_in_traits))

Il est désormais possible d'inclure des constantes au sein d'un Trait.
La syntaxe suivante est donc désormais valide :



```php
trait T {
   public const CONSTANT = 42;

   public function doSomething(): void {
       // Fatal Error
       echo T::CONSTANT;

       // OK
       echo self::CONSTANT;
       echo static::CONSTANT;
       echo $this::CONSTANT;
   }
}
```

### Retrait du support de _libmysql_ (_Remove support for libmysql from mysqli_ : [RFC](https://wiki.php.net/rfc/mysqli_support_for_libmysql))


Le support de la bibliothèque _libmysql_ a été retiré de PHP, pour ne conserver désormais que le support de _mysqlnd_. Si vous utilisez PHP avec MySQL (que ce soit avec l'extension PHP _mysqli_ ou avec _PDO_mysql_), vous ne devriez même pas vous en rendre compte : _mysqlnd_ est utilisée par défaut depuis… PHP 5.4 (sortie en 2012).

### Liste complète des RFC
La liste complète des apports de cette nouvelle version est [consultable ici](https://wiki.php.net/rfc#php_82).

PHP 8.3
-----------
La prochaine version sera la 8.3, [prévue (pour l'instant) pour novembre 2023](https://wiki.php.net/todo/php83).
La liste des nouvelles fonctionnalités n'est évidemment pas encore arrêtée, mais on peut d'ores et déjà [la retrouver ici](https://wiki.php.net/rfc#php_83).