## Autres changements

### Core changes

#### FFI

FFI::load() est désormais autorisé pendant le préchargement quand opcache.preload_user est l'utilisateur système actuel. Précédemment, appeler FFI::load() n'était pas possible pendant le préchargement si la directive opcache.preload_user était définie.

#### FPM

Les test FPM CLI échouent désormais si le chemin du socket est plus long que ce que l'OS supporte.

#### Opcache

Dans les SAPI CLI et phpdbg, le préchargement ne nécessite plus que la directive opcache.preload_user soit définie lorsque PHP est exécuté en tant que root. Dans les autres SAPI, cette directive est requise lorsque PHP est exécuté en tant que root car le préchargement est effectué avant que le SAPI ne passe à un utilisateur non privilégié.

#### Streams

Bloquer fread() sur une connexion de socket retourne immédiatement s'il y a des données tamponnées au lieu d'attendre plus de données.

Un stream de mémoire ne retourne plus d'erreur si le décalage de recherche est au-delà de la fin. A la place, la mémoire sera augmentée à la prochaine écriture et les données entre l'ancienne fin et le décalage sont remplies de zéros, similaire à la façon dont les fichiers fonctionnent.

Les opérations d'accès stat() comme file_exists() et similaires utiliseront désormais le chemin réel au lieu du chemin du stream. Ceci est cohérent avec l'ouverture du stream.

### Changement dans les modules SAPI

#### CLI

Les streams `STDOUT`, `STDERR` et `STDIN` ne sont plus fermés à la destruction de la ressource qui est principalement lorsque le CLI se termine. Il est cependant toujours possible de fermer explicitement ces streams en utilisant fclose() et similaires.

### Fonctions changées

#### Core

gc_status() a ajouté les 8 champs suivantes:

- `"running"` => bool
- `"protected"` => bool
- `"full"` => bool
- `"buffer_size"` => int
- `"application_time"` => float: Le temps total d'application, en secondes (y compris le temps de collecte)
- `"collector_time"` => float: Le temps passé à collecter les cycles, en secondes (y compris le temps de destructeur et le temps de libération)
- `"destructor_time"` => float: Le temps passé à exécuter les destructeurs pendant la collecte des cycles, en secondes
- `"free_time"` => float: Le temps passé à libérer les valeurs pendant la collecte des cycles, en secondes

class_alias() supporte désormais la création d'un alias sur les classes internes.

Changer open_basedir à l'exécution en utilisant `ini_set('open_basedir', ...);` n'accepte plus les chemins contenant le répertoire parent (`..`). Précédemment, seuls les chemins commençant par `..` étaient interdits. Ceci pouvait facilement être contourné en préfixant le chemin par `./`.

Les gestionnaires d'exceptions utilisateur attrapent désormais les exceptions pendant l'arrêt.

Le HTML résultant de highlight_string() et highlight_file() a changé. Les espaces entre les balises HTML extérieures sont supprimés. Les sauts de ligne et les espaces ne sont plus convertis en entités HTML. Tout le HTML est maintenant enveloppé dans une balise `<pre>`. La balise `<span>` extérieure a été fusionnée avec la balise `<code>`.

#### Calendar

easter_date() supporte désormais les années de 1970 à 2 000 000 000 sur les systèmes 64 bits, précédemment il ne supportait que les années de 1970 à 2037.

#### Curl

curl_getinfo() supporte désormais deux nouvelles constantes : `CURLINFO_CAPATH` et `CURLINFO_CAINFO`. Si option est `null`, les deux clés suivant sont présentes : `"capath"` et `"cainfo"`.

#### DOM

Le type de retour de DOMCharacterData::appendData() a été changé en true.

DOMDocument::loadHTML(), DOMDocument::loadHTMLFile(), et DOMDocument::loadXML() ont désormais un type de retour provisoire de bool. Précédemment, cela était documenté comme ayant un type de retour de `DOMDocument|bool`, mais, à partir de PHP 8.0.0, DOMDocument ne peut pas être retourné car il n'est plus statiquement appelable.

#### Gd

La signature de imagerotate() a changé. Le paramètre `$ignore_transparent` a été supprimé, car il était ignoré depuis PHP 5.5.0.

#### Intl

datefmt_set_timezone() (et ses alias IntlDateformatter::setTimeZone()) retourn désormais `true` en cas de succès, avant `null` étais retourné.

IntlBreakiterator::setText() retourne désormais `false` en cas d'échec, précédemment `null` était retourné. Il retourne désormais `true` en cas de succès, précédemment `null` était retourné.

IntlChar::enumCharNames() retourne désormais un booléen. Précédemment, il retournait `null` en cas de succès et `false` en cas d'échec.

IntlDateFormatter::__construct() lance une exception `U_ILLEGAL_ARGUMENT_ERROR` lorsqu'une locale invalide a été définie.

#### MBString

mb_strtolower() et mb_convert_case() implémentent des règles de casse conditionnelles pour la lettre grecque sigma. Pour mb_strtolower(), la casse conditionnelle s'applique uniquement aux modes `MB_CASE_LOWER`, et `MB_CASE_TITLE`, pas aux modes `MB_CASE_LOWER_SIMPLE` et `MB_CASE_TITLE_SIMPLE`.

mb_decode_mimeheader() interprète les tirets bas dans les mots encodés MIME QPrint comme requis par la RFC 2047 ; ils sont convertis en espaces. Les tirets bas doivent être encodés en `"=5F"` dans de tels mots encodés MIME.

Dans de rare cas, mb_encode_mimeheader() va encoder sa chaîne de caractères d'entrée là où elle la passerait en ASCII brut en PHP 8.2.

mb_encode_mimeheader() ne supprime plus les octets NUL (zéro) lors de l'encodage QPrint de la chaine d'entrée. Cela corrompait précédemment les chaines dans certains encodages de texte, en particulier UTF-16 et UTF-32, par mb_encode_mimeheader.

mb_detect_encoding() en mode "non-strict" se comporte désormais comme décrit dans la documentation. Auparavant, il retournait `false` si le même octet (par exemple, le premier octet) de la chaine d'entrée était invalide dans tous les encodages candidats. Plus généralement, il éliminait les encodages candidats de la considération lorsqu'un octet invalide était vu, et si le même octet d'entrée éliminait tous les encodages restants encore sous considération, il retournait `false`. D'autre part, si tous les encodages candidats sauf un étaient éliminés de la considération, il retournait le dernier restant sans tenir compte du nombre d'erreurs d'encodage qui pourraient être rencontrées plus tard dans la chaine. Ceci est différent du comportement décrit dans la documentation, qui dit : "Si strict est défini sur false, l'encodage le plus proche sera retourné."

#### mysqli

mysqli_fetch_object() lance désormais une ValueError au lieu d'une Exception lorsque l'argument `$constructor_args` n'est pas vide avec la classe n'ayant pas de constructeur.

mysqli_poll() lance désormais une ValueError lorsque ni l'argument `$read` ni l'argument `$error` ne sont passés.

mysqli_field_seek() et mysqli_result::field_seek() précise désormais le type de retour comme true au lieu de bool.

#### ODBC

odbc_autocommit() accepte désormais `null` pour le paramètre `$enable`. Passer `null` a le même comportement que passer un seul paramètre, indiquant si la fonctionnalité autocommit est activée ou non.

#### PGSQL

pg_fetch_object() lance désormais une ValueError à la place d'une Exception lorsque l'argument`$constructor_args` n'est pas vide avec la classe n'ayant pas de constructeur.

pg_insert() lance désormais une ValueError au lieu d'une Exception lorsque la table spécifiée est invalide.

pg_insert() et pg_convert() lancent une ValueError ou une TypeError à la place d'un `E_WARNING` lorsque la valeur/type d'un champ ne correspond pas correctement au type de PostgreSQL.

Le paramètre `$row` de pg_fetch_result(), pg_field_prtlen(), et pg_field_is_null() est désormais nullable.

#### Random

Changement de mt_srand() et srand() pour ne pas vérifier le nombre d'arguments pour déterminer si une graine aléatoire doit être utilisée. Passer `null` générera une graine aléatoire, `0` utilisera zéro comme graine. Les fonctions sont désormais cohérentes avec Random\Engine\Mt19937::__construct().

#### Reflection

Le type de retour de ReflectionClass::getStaticProperties() n'est désormais plus nullable.

#### Standard

Le `E_NOTICE` émis par unserialize() a été promu en `E_WARNING`.

unserialize() émet désormais un `E_WARNING` si l'entrée contient des octets non consommés.

array_pad() n'est désormais limité que par le nombre maximum d'éléments qu'un tableau peut contenir. Auparavant, il était seulement possible d'ajouter au plus 1 048 576 éléments à la fois.

strtok() lance maintenant un `E_WARNING` si le token n'est pas fourni lors du démarrage de la tokenisation.

password_hash() chaîne désormais l'exception sous-jacente Random\RandomException dans la `$previous` Exception de `ValueError` lorsque la génération de sel échoue.

Si un tableau est utilisé comme `$command` pour proc_open(), il doit désormais avoir au moins un élément non vide. Sinon, une ValueError est lancée.

proc_open() retourne désormais `false` si le tableau `$command` est une commande invalide au lieu d'un objet de ressource qui produit un avertissement plus tard. C'était déjà le cas pour Windows, mais c'est maintenant aussi le cas si une implémentation posix_spawn est utilisée (la plupart des plates-formes Linux, BSD et MacOS). Il reste quelques anciennes plates-formes où ce comportement n'a pas changé car posix_spawn n'est pas pris en charge là-bas.

array_sum() et array_product() émettent désormais un avertissement lorsque les valeurs du tableau ne peuvent pas être converties en int/float. Auparavant, les tableaux et les objets étaient ignorés tandis que chaque autre valeur était convertie en int. De plus, les objets qui définissent une conversion numérique (par exemple GMP) sont désormais convertis au lieu d'être ignorés.

Le `$decimals` de number_format() gère désormais les entiers négatifs. Arrondir avec une valeur négative pour `$decimals` signifie que `$num` est arrondi à `$decimals` chiffres significatifs avant le séparateur décimal. Auparavant, les entiers négatifs pour `$decimals` étaient silencieusement ignorés et le nombre était arrondi à zéro décimales.

Un nouveau argument `$before_needle` a été ajouté à strrchr(). Il se comporte comme son homologue dans les fonctions strstr() ou stristr().

str_getcsv() et fgetcsv() retournent désormais une chaine vide au lieu d'une chaine avec un seul octet nul pour le dernier champ qui ne contient qu'une enceinte non terminée.

### Autres changements aux extensions

#### Core

Utiliser les opérateurs d'incrémentation/décrémentation (`++`/`--`) sur des valeurs de type bool émet désormais des avertissements. Cela est dû au fait que cela n'a actuellement aucun effet, mais se comportera comme `$bool += 1` à l'avenir. Using the increment/decrement

Utiliser l'opérateur de décrémentation (`--`) sur des valeurs de type null émet désormais des avertissements. Cela est dû au fait que cela n'a actuellement aucun effet, mais se comportera comme `$null -= 1` à l'avenir.

Les objets internes qui implémentent un cast _IS_NUMBER mais pas un gestionnaire do_operator qui remplace l'addition et la soustraction peuvent désormais être incrémentés et décrémentés comme si on faisait `$o += 1` ou `$o -= 1`.

#### DOM

Le mécanisme de durée de vie du DOM a été retravaillé de telle sorte que les nœuds implicitement supprimés peuvent toujours être récupérés. Auparavant, cela entraînait une exception.

#### SQLite3

La classe SQLite3 lance une SQLite3Exception (extension de Exception) à la place de Exception.

Le code d'erreur SQLite est désormais passé dans le code d'erreur de l'exception au lieu d'être inclus dans le message d'erreur.

### Changement de la gestion du fichier INI

- Les paramètres INI `assert.*` ont été dépréciés. Cela comprend les paramètres INI suivants :

  - assert.active
  - assert.bail
  - assert.callback
  - assert.exception
  - assert.warning
  Si la valeur du paramètre est égale à la valeur par défaut, aucun avertissement de dépréciation n'est émis. Le paramètre INI zend.assertions devrait être utilisé à la place.

- zend.max_allowed_stack_size est une nouvelle directive INI pour définir la taille maximale de la pile autorisée. Les valeurs possibles sont `0` (détecter la taille maximale de la pile du processus ou du thread), `-1` (pas de limite), ou un nombre positif d'octets. La valeur par défaut est `0`. Lorsqu'il n'est pas possible de détecter la taille maximale de la pile du processus ou du thread, une valeur par défaut système connue est utilisée. Définir cette valeur trop élevée a le même effet que la désactivation de la limite de taille de la pile. Les fibres utilisent fiber.stack_size comme taille de pile maximale autorisée. Une Error est lancée lorsque la pile d'appel du processus dépasse zend.max_allowed_stack_size-zend.reserved_stack_size octets, pour éviter les erreurs de segmentation dues à un dépassement de pile, dans le but de faciliter le débogage. La taille de la pile augmente pendant les récursions non contrôlées impliquant des fonctions internes ou les méthodes magiques __toString(), __clone(), __sleep(), __destruct(). Cela n'est pas lié aux débordements de tampon de pile, et n'est pas une fonctionnalité de sécurité.

- zend.reserved_stack_size est une nouvelle directive INI pour définir la taille de la pile réservée, en octets. Cela est soustrait de la taille maximale de la pile autorisée, en tant que tampon, lors de la vérification de la taille de la pile.

### Performance

#### DOM

Itérer sur un DOMNodeList utilise désormais un cache. Par conséquent, demander des éléments ne prend plus de temps quadratique par défaut.

Obtenir le contenu textuel des nœuds évite désormais une allocation, ce qui entraîne un gain de performance.

DOMChildNode::remove() s'exécute désormais en O(1) performance.

#### Standard

Le drapeau file() pour la vérification des erreurs est désormais environ 7% plus rapide.

#### SPL

RecursiveDirectoryIterator effectue désormais moins d'E/S lors du parcours d'un répertoire.