## Modifications entrainant une incompatibilité ascendante

### Cœur de PHP

#### Comparaison entre une chaîne de caractères et un nombre

Les comparaisons non strictes entre les nombres et les chaînes non numériques fonctionnent désormais en transformant le nombre en chaîne et en comparant les chaînes. Les comparaisons entre les nombres et les chaînes numériques continuent de fonctionner comme auparavant. Cela signifie notamment que `0 == "not-a-number"` est désormais considéré comme faux.

Comparaison | Avant | Après
--- | --- | ---
`0 == "0"` | `true` | `true`
`0 == "0.0"` | `true` | `true`
`0 == "foo"` | `true` | `false`
`0 == ""` | `true` | `false`
`42 == " 42"` | `true` | `true`
`42 == "42foo"` | `true` | `false`

#### Autres changements incompatibles

- `match` est désormais un mot-clé réservé.

- `mixed` est désormais un mot réservé, il ne peut donc pas être utilisé pour nommer une classe, une interface ou un trait, et il est également interdit de l'utiliser dans les espaces de noms.

- Les échecs d'assertion sont maintenant lancés par défaut. Si l'ancien comportement est souhaité, `assert.exception=0` peut être défini dans les paramètres INI.

- Les méthodes portant le même nom que la classe ne sont plus interprétées comme des constructeurs. La méthode __construct() doit être utilisée à la place.

- La possibilité d'appeler des méthodes non statiques de manière statique a été supprimée. Ainsi, is_callable() échouera lors de la vérification d'une méthode non statique avec un nom de classe (il faut vérifier avec une instance d'objet).

- Les castings `(real)` et `(unset)` ont été supprimés.

- La directive ini track_errors a été supprimée. Cela signifie que php_errormsg n'est plus disponible. La fonction error_get_last() peut être utilisée à la place.

- La possibilité de définir des constantes insensibles à la casse a été supprimée. Le troisième argument de define() ne peut plus être `true`.

- La possibilité de spécifier un autochargeur en utilisant une fonction __autoload() a été supprimée. spl_autoload_register() doit être utilisée à la place.

- L'argument `errcontext` ne sera plus passé aux gestionnaires d'erreurs personnalisés paramétrés avec set_error_handler().

- create_function() a été supprimée. Les fonctions anonymes peuvent être utilisées à la place.

- each() a été supprimée. `foreach` ou ArrayIterator doivent être utilisées à la place.

- La possibilité de délier this des fermetures qui ont été créées à partir d'une méthode, en utilisant Closure::fromCallable() ou ReflectionMethod::getClosure() a été supprimée.

- La possibilité de délier this des fermetures appropriées qui contiennent des utilisations de this a également été supprimée.

- La possibilité d'utiliser array_key_exists() avec des objets a été supprimée. isset() ou property_exists() peuvent être utilisées à la place.

- Le comportement de array_key_exists() concernant le type du paramètre `key` a été rendu cohérent avec isset() et l'accès normal aux tableaux. Tous les types de clés utilisent maintenant les coercions habituels et les clés de type tableau/objet lancent une TypeError.

- Tout tableau dont la première clé numérique est un nombre n utilisera n+1 pour sa prochaine clé implicite, même si n est négatif.

- Le niveau de signalement des erreurs par défaut (error_reporting) est désormais `E_ALL`. Auparavant, il excluait `E_NOTICE` et `E_DEPRECATED`.

- display_startup_errors est désormais activée par défaut.

- L'utilisation de parent à l'intérieur d'une classe qui n'a pas de parent entraîne désormais une erreur fatale à la compilation.

- L'opérateur `@` ne silence plus les erreurs fatales (`E_ERROR`, `E_CORE_ERROR`, `E_COMPILE_ERROR`, `E_USER_ERROR`, `E_RECOVERABLE_ERROR`, `E_PARSE`). Les gestionnaires d'erreurs qui s'attendent à ce que error_reporting soit égal à `0` lorsque `@` est utilisé, doivent être ajustés pour utiliser une vérification de masque à la place :

  `<?php
  // Remplacer
  function my_error_handler($err_no, $err_msg, $filename, $linenum) {
  if (error_reporting() == 0) {
  return false;
  }
  // ...
  }
  // Par
  function my_error_handler($err_no, $err_msg, $filename, $linenum) {
  if (!(error_reporting() & $err_no)) {
  return false;
  }
  // ...
  }
  ?>`

  En outre, il faut veiller à ce que les messages d'erreur ne soient pas affichés dans les environnements de production, ce qui peut entraîner des fuites d'informations. Veillez à ce que l'option `display_errors=Off` soit utilisée en conjonction avec la journalisation des erreurs.

- `#[` n'est plus interprété comme le début d'un commentaire, car cette syntaxe est désormais utilisée pour les attributs.

- Les erreurs d'héritage dues à des signatures de méthodes incompatibles (violations de LSP) génèrent désormais une erreur fatale. Auparavant, un avertissement était généré dans certains cas.

- La priorité de l'opérateur de concaténation a été modifiée par rapport aux décalages de bits, à l'addition ainsi qu'à la soustraction.

  `<?php
  echo "Sum: " . $a + $b;
  // était auparavant interprété comme:
  echo ("Sum: " . $a) + $b;
  // est désormais interprété comme:
  echo "Sum:" . ($a + $b);
  ?>`

- Les arguments avec une valeur par défaut qui se résout en `null` à l'exécution ne marqueront plus implicitement le type d'argument comme nullable. Il faut utiliser soit un type explicite nullable, soit une valeur par défaut explicite `null` à la place.

  `<?php
  // Remplacer
  function test(int $arg = CONST_RESOLVING_TO_NULL) {}
  // Par
  function test(?int $arg = CONST_RESOLVING_TO_NULL) {}
  // Ou
  function test(int $arg = null) {}
  ?>`

- Un certain nombre d'avertissements ont été convertis en exceptions Error:

  - Tentative d'écriture sur une propriété d'un non-objet. Auparavant, cela créait implicitement un objet stdClass pour null, false et les chaînes vides.
  - Tentative d'ajout d'un élément à un tableau pour lequel la clé PHP_INT_MAX est déjà utilisée.
  - Tentative d'utilisation d'un type invalide (tableau ou objet) comme clé de tableau ou comme index de chaîne de caractères.
  - Tentative d'écriture sur un index de tableau d'une valeur scalaire.
  - Tentative de décompactage d'un non tableau/Traversable.
  - Tentative d'accès à des constantes non qualifiées qui sont indéfinies. Auparavant, les accès à des constantes non qualifiées entraînaient un avertissement et étaient interprétés comme des chaînes de caractères.
  - Passer le nombre incorrect d'arguments à une fonction intégrée non variadique entraînera le déclenchement d'une ArgumentCountError.
  - Passer des types compteurs invalides à count() entraînera le déclenchement d'une TypeError.

  Un certain nombre de notices ont été convertis en avertissements :

  - Tentative de lecture d'une variable non définie.
  - Tentative de lecture d'une propriété non définie.
  - Tentative de lecture d'une clé de tableau non définie.
  - Tentative de lecture d'une propriété d'un non-objet.
  - Tentative d'accès à un index de tableau d'un non-tableau.
  - Tentative de conversion d'un tableau en chaîne de caractères.
  - Tentative d'utilisation d'une ressource comme clé de tableau.
  - Tentative d'utilisation de null, d'un booléen ou d'un nombre flottant comme index de chaîne.
  - Tentative de lecture d'un index de chaîne hors limites.
  - Tentative d'affectation d'une chaîne vide à un index de chaîne.

- Tenter d'assigner plusieurs octets à un index de chaîne émettra désormais un avertissement.

- Les caractères inattendus dans les fichiers source (tels que les octets NUL à l'extérieur des chaînes de caractères) entraîneront désormais une exception ParseError au lieu d'un avertissement de compilation.

- Les exceptions non capturée passent maintenant par un "arrêt propre", ce qui signifie que les destructeurs seront appelés après une exception non capturée.

- L'erreur fatale à la compilation "Only variables can be passed by reference" a été retardée jusqu'à l'exécution, et convertie en une exception Error "Argument cannot be passed by reference".

- Certaines notices "Only variables should be passed by reference" ont été convertis en exception "Argument cannot be passed by reference".

- Le nom généré pour les classes anonymes a changé. Il inclura désormais le nom du premier parent ou interface :

  `<?php
  new class extends ParentClass {};
  // -> ParentClass@anonymous
  new class implements FirstInterface, SecondInterface {};
  // -> FirstInterface@anonymous
  new class {};
  // -> class@anonymous
  ?>`

  Le nom ci-dessus est toujours suivi d'un octet NUL et d'un suffixe unique.

- Les références de méthodes de traits non absolues dans les adaptations d'alias de traits doivent désormais être non ambiguës :

  `<?php
  class X {
  use T1, T2 {
  func as otherFunc;
  }
  function func() {}
  }
  ?>`

  Si `T1::func()` et `T2::func()` existent tous les deux, ce code était auparavant accepté silencieusement, et func était supposé faire référence à `T1::func`. Désormais, il génère une erreur fatale, et `T1::func` ou `T2::func` doivent être écrit explicitement.

- La signature des méthodes abstraites définies dans les traits est maintenant vérifiée par rapport à la méthode dans la classe d'implémentation:

  `<?php
  trait MyTrait {
  abstract private function neededByTrait(): string;
  }
  class MyClass {
  use MyTrait;
  // Error, because of return type mismatch.
  private function neededByTrait(): int { return 42; }
  }
  ?>`

- Les fonctions désactivées sont désormais traitées exactement comme des fonctions inexistantes. L'appel d'une fonction la signalera comme inconnue, et il est désormais possible de redéfinir une fonction désactivée.

- Les enveloppes de flux `data://` ne sont plus inscriptibles, ce qui correspond au comportement documenté.

- Les opérateurs arithmétiques et binaires `+`, `-`, `*`, `/`, `**`, `%`, `<<`, `>>`, `&`, `|`, `^`, `~`, `++`, `--` lancent désormais systématiquement une TypeError lorsqu'un des opérandes est un tableau, resource ou un objet non surchargé. La seule exception à cette règle est l'opération de fusion de tableau `+`, qui reste supportée.

- La conversion de nombres flottants en chaînes de caractères se fera désormais indépendamment de la localisation.

  `<?php
  setlocale(LC_ALL, "de_DE");
  $f = 3.14;
  echo $f, "\n";
  // Previously: 3,14
  // Now: 3.14
  ?>`

  Voir printf(), number_format() et NumberFormatter() pour personnaliser le formatage des nombres.

- La prise en charge des accolades pour l'accès aux index a été supprimée.

  `<?php
  // Instead of:
  $array{0};
  $array{"key"};
  // Write:
  $array[0];
  $array["key"];
  ?>`

- L'application du modificateur final sur une méthode privée produira désormais un avertissement à moins que cette méthode ne soit le constructeur.

- Si un constructeur d'objet appelle exit(), le destructeur d'objet n'est plus appelé. Cela correspond au comportement lorsque le constructeur lance une exception.

- Les noms d'espace de nommage ne peuvent plus contenir d'espace blanc : Alors que `Foo\Bar` sera reconnu comme un nom à espace de noms, `Foo \ Bar` ne le sera pas. Inversement, les mots-clés réservés sont désormais autorisés en tant que segments d'espace de noms, ce qui peut également modifier l'interprétation du code : `new\x` est maintenant la même chose que `constant('new\x')`, et pas `new \x()`.

- Les ternaires imbriqués nécessitent désormais des parenthèses explicites.

- debug_backtrace() et Exception::getTrace() ne fourniront plus de références aux arguments. Il ne sera plus possible de modifier les arguments d'une fonction par le biais de la trace.

- La gestion des chaînes numériques a été modifiée pour être plus intuitive et moins sujette aux erreurs. L'espacement de fin est désormais autorisé dans les chaînes numériques pour des raisons de cohérence avec le traitement des espaces de tête. Ceci affecte principalement :

  - La fonction is_numeric()
  - Les comparaisons entre deux chaîne de caractères
  - Les déclarations de type
  - Les opérations d'incrémentation et de décrémentation

  Le concept de "chaînes débutant numériquement" a été pratiquement abandonné ; les cas où il subsiste existent afin de faciliter la migration. Les chaînes de caractères qui émettaient une erreur `E_NOTICE` "A non wellformed numeric value encountered" émettront désormais une erreur `E_WARNING` "A nonumeric value encountered" et toutes les chaînes qui émettaient une erreur `E_WARNING` "A non-numeric value encountered" émettront désormais une erreur de type TypeError. Ceci affecte principalement :

  - les opérations arithmétiques
  - les opérations binaires

  Cette modification de `E_WARNING` à TypeError affecte également l'erreur `E_WARNING` "Illegal string offset 'string'" pour les index de chaîne illégaux. Le comportement des transformations explicites en int/float à partir de chaînes de caractères n'a pas été modifié.

- Les arguments et les types de retour des méthodes magiques seront désormais vérifiés s'ils ont été déclarés. Les signatures doivent correspondre à la liste suivante :

  - `__call(string $name, array $arguments): mixed`
  - `__callStatic(string $name, array $arguments): mixed`
  - `__clone(): void`
  - `__debugInfo(): ?array`
  - `__get(string $name): mixed`
  - `__invoke(mixed $arguments): mixed`
  - `__isset(string $name): bool`
  - `__serialize(): array`
  - `__set(string $name, mixed $value): void`
  - `__set_state(array $properties): object`
  - `__sleep(): array`
  - `__unserialize(array $data): void`
  - `__unset(string $name): void`
  - `__wakeup(): void`

- Les clés des tableaux call_user_func_array() seront désormais interprétées comme des noms de paramètres, au lieu d'être ignorées silencieusement.

- La déclaration d'une fonction appelée `assert()` à l'intérieur d'un espace de noms n'est plus autorisée, et émet une `E_COMPILE_ERROR`. La fonction assert() est soumise à un traitement spécial par le moteur, ce qui peut conduire à un comportement incohérent lors de la définition d'une fonction de l'espace de noms portant le même nom.

### Migration des ressources vers les objets

Plusieurs resources ont été migrées en objets. Les vérifications de la valeur retournée utilisant is_resource() devraient être remplacées par des vérifications pour `false`.

- curl_init() retourne désormais un objet CurlHandle plutôt qu'une resource. La fonction curl_close() n'a plus d'effet, l'instance CurlHandle est automatiquement détruite si elle n'est plus référencée.

- curl_multi_init() retourne désormais un objet CurlMultiHandle plutôt qu'un resource. La fonction curl_multi_close() n'a plus d'effet, l'instance CurlMultiHandle est automatiquement détruite si elle n'est plus référencée.

- curl_share_init() retourne désormais un objet CurlShareHandle plutôt qu'un resource. La fonction curl_share_close() n'a plus d'effet, l'instance CurlShareHandle est automatiquement détruite si elle n'est plus référencée.

- enchant_broker_init() retourne désormais un objet EnchantBroker plutôt qu'une resource.

- enchant_broker_request_dict() et enchant_broker_request_pwl_dict() retournent désormais un objet EnchantDictionary au lieu d'une resource.

- L'extension GD utilise désormais les objets GdImage comme structure de données sous-jacente pour les images, plutôt que des resources. La fonction imagedestroy() n'a plus d'effet ; à la place, l'instance est automatiquement détruite si elle n'est plus référencée. GdImage est automatiquement détruite si elle n'est plus référencée.

- openssl_x509_read() et openssl_csr_sign() retournent désormais un objet OpenSSLCertificate plutôt qu'une resource. La fonction openssl_x509_free() est obsolète et n'a plus d'effet, l'instance OpenSSLCertificate est automatiquement détruite si elle n'est plus référencée.

- openssl_csr_new() retourne désormais un objet OpenSSLCertificateSigningRequest plutôt qu'une resource.

- openssl_pkey_new() retourne désormais un objet OpenSSLAsymmetricKey plutôt qu'une resource. La fonction openssl_pkey_free() est obsolète et n'a plus d'effet, l'instance OpenSSLAsymmetricKey est automatiquement détruite si elle n'est plus référencée.

- shmop_open() retourne désormais un objet Shmop plutôt qu'une resource. La fonction shmop_close() n'a plus d'effet, et est obsolète ; l'instance Shmop est automatiquement détruite si elle n'est plus référencée.

- socket_create(), socket_create_listen(), socket_accept(), socket_import_stream(), socket_addrinfo_connect(), socket_addrinfo_bind(), et socket_wsaprotocol_info_import() retournent désormais un objet Socket plutôt qu'une resource. socket_addrinfo_lookup() retourne désormais un tableau d'objets AddressInfo au lieu de resources.

- msg_get_queue() retourne désormais un objet SysvMessageQueue plutôt qu'une resource.

- sem_get() retourne désormais un objet SysvSemaphore plutôt qu'une resource.

- shm_attach() retourne désormais un objet SysvSharedMemory plutôt qu'une resource.

- xml_parser_create() et xml_parser_create_ns() retournent désormais un objet XMLParser au lieu d'une resource. La fonction xml_parser_free() n'a plus d'effet, l'instance de XMLParser est automatiquement détruite si elle n'est plus référencée.

- Les fonctions XMLWriter acceptent et retournent désormais, respectivement, des objets XMLWriter au lieu de resources.

- inflate_init() retourne désormais un objet InflateContext plutôt qu'une resource.

- deflate_init() retourne désormais un objet DeflateContext plutôt qu'une resource.

### COM et .Net (Windows)

La possibilité d'importer des constantes insensibles à la casse à partir de bibliothèques de types a été supprimée. Le deuxième argument de com_load_typelib() ne peut plus être false ; com.autoregister_casesensitive ne peut plus être désactivé ; les marqueurs insensibles à la casse dans com.typelib_file sont ignorés.

### CURL

`CURLOPT_POSTFIELDS` n'accepte plus les objets sous forme de tableaux. Pour interpréter un objet comme un tableau, il faut effectuer un cast explicite `(array)`. Cela s'applique également aux autres options acceptant les tableaux.

### Date et heure

mktime() et gmmktime() requièrent désormais au moins un argument. time() peut être utilisée pour obtenir l'horodatage actuel.

### DOM

Les classes non implémentées de l'extension DOM qui n'avaient pas de comportement et contenaient des données de test ont été supprimées. Ces classes ont également été supprimées dans la dernière version de la norme du standard DOM :

- DOMNameList
- DomImplementationList
- DOMConfiguration
- DomError
- DomErrorHandler
- DOMImplementationSource
- DOMLocator
- DOMUserDataHandler
- DOMTypeInfo
- DOMStringExtend

Les méthodes non implémentées de l'extension DOM qui n'avaient pas de comportement ont été supprimées :

- DOMNamedNodeMap::setNamedItem()
- DOMNamedNodeMap::removeNamedItem()
- DOMNamedNodeMap::setNamedItemNS()
- DOMNamedNodeMap::removeNamedItemNS()
- DOMText::replaceWholeText()
- DOMNode::compareDocumentPosition()
- DOMNode::isEqualNode()
- DOMNode::getFeature()
- DOMNode::setUserData()
- DOMNode::getUserData()
- DOMDocument::renameNode()

### Enchant

- enchant_broker_list_dicts(), enchant_broker_describe() et enchant_dict_suggest() retourneront désormais un tableau vide au lieu de `null`.

### Exif

read_exif_data() a été supprimée ; exif_read_data() doit être utilisée à la place.

### Filter

- Les drapeaux `FILTER_FLAG_SCHEME_REQUIRED` et `FILTER_FLAG_HOST_REQUIRED` pour le filtre `FILTER_VALIDATE_URL` ont été supprimés. Le `schéma` et l'`hôte` sont (et ont toujours été) nécessaires.

- Les sources `INPUT_REQUEST` et `INPUT_SESSION` pour filter_input() etc. ont été supprimées. Elles n'ont jamais été mises en œuvre et leur utilisation a toujours généré un avertissement.

### GD

- La fonction obsolète image2wbmp() a été supprimée.

- Les fonctions obsolètes png2wbmp() et jpeg2wbmp() ont été supprimées.

- Le paramètre par défaut `mode` d'imagecropauto() n'accepte plus `-1`. `IMG_CROP_DEFAULT` doit être utilisé à la place.

- Sous Windows, php_gd2.dll a été renommé en php_gd.dll.

### GMP

gmp_random() a été supprimée. L'une des fonctions gmp_random_range() ou gmp_random_bits() doit être utilisée à la place.

### Iconv

Les implémentations iconv qui ne définissent pas correctement errno en cas d'erreur ne sont plus supportées.

### IMAP

- L'argument inutilisé `default_host` de imap_headerinfo() a été supprimé.

- La fonction imap_header() qui est un alias de imap_headerinfo() a été supprimée.

### Fonctions d'internationalisation

- La constante obsolète `INTL_IDNA_VARIANT_2003` a été supprimée.

- La constante obsolète `Normalizer::NONE` a été supprimée.

### LDAP

- Les fonctions ldap_sort(), ldap_control_paged_result() et ldap_control_paged_result_response() ont été supprimées.

- L'interface de ldap_set_rebind_proc() a changée ; le paramètre `callback` n'accepte plus les chaînes vides ; `null` doit être utilisé à la place.

### MBString

- La directive mbstring.func_overload a été supprimée. Les constantes `MB_OVERLOAD_MAIL`, `MB_OVERLOAD_STRING`, et `MB_OVERLOAD_REGEX` ont également été supprimées. Enfin, les entrées `"func_overload"` et `"func_overload_list"` dans mb_get_info() ont été supprimées.

- mb_parse_str() ne peut plus être utilisée sans spécifier un tableau de résultats.

- Un certain nombre d'alias mbregex obsolètes ont été supprimés. Voir la liste suivante pour savoir quelles fonctions doivent être utilisées à la place :

  - mbregex_encoding() → mb_regex_encoding()
  - mbereg() → mb_ereg()
  - mberegi() → mb_eregi()
  - mbereg_replace() → mb_ereg_replace()
  - mberegi_replace() → mb_eregi_replace()
  - mbsplit() → mb_split()
  - mbereg_match() → mb_ereg_match()
  - mbereg_search() → mb_ereg_search()
  - mbereg_search_pos() → mb_ereg_search_pos()
  - mbereg_search_regs() → mb_ereg_search_regs()
  - mbereg_search_init() → mb_ereg_search_init()
  - mbereg_search_getregs() → mb_ereg_search_getregs()
  - mbereg_search_getpos() → mb_ereg_search_getpos()
  - mbereg_search_setpos() → mb_ereg_search_setpos()

- Le modificateur `e` pour mb_ereg_replace() a été supprimé. mb_ereg_replace_callback() doit être utilisé à la place.

- Un argument de motif autre qu'une chaîne de caractères à mb_ereg_replace() sera désormais interprété comme une chaîne de caractères au lieu d'un point de code ASCII. Le comportement précédent peut être restauré avec un appel explicite à chr().

- L'argument `needle` pour mb_strpos(), mb_strrpos(), mb_stripos(), mb_strripos(), mb_strstr(), mb_stristr(), mb_strrchr() et mb_strrichr() peut désormais être vide.

- Le paramètre `is_hex`, qui n'était pas utilisé en interne, a été supprimé de mb_decode_numericentity().

- L'ancien comportement consistant à passer l'encodage comme troisième argument au lieu d'un offset pour la fonction mb_strrpos() a été supprimé ; un index explicite de `0` avec l'encodage doit être fourni comme quatrième argument.

- Les alias de codage de caractères `ISO_8859-*` ont été remplacés par `ISO8859-*` pour une meilleure interopérabilité avec l'extension iconv. Les alias mbregex ISO 8859 avec des traits de soulignement`(ISO_8859_*` et `ISO8859_*`) ont également été supprimés.

- mb_ereg() et mb_eregi() retourneront désormais le booléen `true` en cas de correspondance réussie. Auparavant, elles retournaient l'entier `1` si `matches` n'était pas passé, ou `max(1, strlen($matches[0]))` si `matches` était passé.

### OCI8

- La classe OCI-Lob s'appelle désormais OCILob, et la classe OCI-Collection s'appelle maintenant OCICollection pour la conformité des noms avec l'outil d'annotation de type arginfo de PHP 8.

- Plusieurs fonctions alias ont été marquées comme obsolètes.

- oci_internal_debug() et son alias ociinternaldebug() ont été supprimés.

### ODBC

- odbc_connect() ne réutilise plus les connexions.

- Le paramètre inutilisé `flags` de odbc_exec() a été supprimé.

### OpenSSL

- openssl_seal() et openssl_open() requièrent désormais le paramètre `method` car l'ancienne valeur par défaut `"RC4"` est considéré comme peu sûr.

### Expressions régulières (compatibles avec Perl)

Lorsque des séquences d'échappement invalides sont passées, elles ne sont plus interprétées comme des littéraux. Ce comportement nécessitait auparavant le modificateur `X` qui est maintenant ignoré.

### Objets de données PHP (PDO)

- Le mode de gestion des erreurs par défaut a été changé de "silencieux" à "exceptions". Voir Erreurs et gestion des erreurs pour plus de détails.

- Les signatures de certaines méthodes PDO ont changé :

  - `PDO::query(string $query, ?int $fetchMode = null, mixed ...$fetchModeArgs)`
  - `PDOStatement::setFetchMode(int $mode, mixed ...$args)`

### PDO ODBC

La directive php.ini pdo_odbc.db2_instance_name a été supprimée.

### PDO MySQL

PDO::inTransaction() indique désormais l'état réel de la transaction de la connexion, plutôt qu'une approximation maintenue par PDO. Si une requête soumise à un "commit implicite" est exécutée, PDO::inTransaction() retournera par la suite `false`, car la transaction n'est plus active.

### PostgreSQL

- La syntaxe obsolète pg_connect() utilisant plusieurs paramètres au lieu d'une chaîne de connexion n'est plus supportée.

- La signature pg_lo_import() et pg_lo_export() qui transmet la connexion comme dernier argument n'est plus supportée. La connexion doit être passée comme premier argument à la place.

- pg_fetch_all() retourne maintenant un tableau vide au lieu de `false` pour les jeux de résultats avec zéro ligne.

### Phar

Les métadonnées associées à un phar ne seront plus automatiquement désérialisées, afin de corriger des vulnérabilités de sécurité potentielles dues à l'instanciation d'objets, à l'autoloading, etc.

### Reflection

- Les signatures de méthodes

  - `ReflectionClass::newInstance($args)`
  - `ReflectionFunction::invoke($args)`
  - `ReflectionMethod::invoke($object, $args)`

  ont été remplacées par :

  - `ReflectionClass::newInstance(...$args)`
  - `ReflectionFunction::invoke(...$args)`
  - `ReflectionMethod::invoke($object, ...$args)`

  Le code qui doit être compatible avec PHP 7 et PHP 8 peut utiliser les signatures suivantes pour être compatible avec les deux versions :

  - `ReflectionClass::newInstance($arg = null, ...$args)`
  - `ReflectionFunction::invoke($arg = null, ...$args)`
  - `ReflectionMethod::invoke($object, $arg = null, ...$args)`

- La méthode ReflectionType::__toString() retourne maintenant une représentation complète de débogage du type, et n'est plus dépréciée. En particulier, le résultat inclura un indicateur de nullité pour les types nullables. Le format de la valeur retournée n'est pas stable et peut changer changer d'une version de PHP à l'autre.

- Les méthodes de réflexion export() ont été supprimées. A la place, les objets de réflexion peuvent être transformés en chaînes de caractères.

- ReflectionMethod::isConstructor() et ReflectionMethod::isDestructor() retournent désormais également `true` pour les méthodes __construct() et __destruct() des interfaces. Auparavant, ce n'était le cas que pour les méthodes des classes et des traits.

- La méthode ReflectionType::isBuiltin() a été déplacée vers ReflectionNamedType. ReflectionUnionType n'a pas cette méthode.

### Sockets

- Les drapeaux obsolètes `AI_IDN_ALLOW_UNASSIGNED` et `AI_IDN_USE_STD3_ASCII_RULES` `flags` pour socket_addrinfo_lookup() ont été supprimés.

### Bibliothèque standard de PHP (SPL)

- SplFileObject::fgetss() a été supprimée.

- SplFileObject::seek() cherche maintenant toujours le début de la ligne. Auparavant, les positions `>=1` recherchaient le début de la ligne suivante.

- SplHeap::compare() spécifie désormais une signature de méthode. Les classes héritées implémentant cette méthode devront désormais utiliser une signature de méthode compatible.

- SplDoublyLinkedList::push(), SplDoublyLinkedList::unshift() et SplQueue::enqueue() retournent désormais void au lieu de `true`.

- spl_autoload_register() lancera désormais toujours une TypeError en cas d'arguments invalides, donc le second argument `do_throw` est ignoré et une notification sera émise s'il est défini à `false`.

- SplFixedArray est maintenant un IteratorAggregate et non plus un Iterator. SplFixedArray::rewind(), SplFixedArray::current(), SplFixedArray::key(), SplFixedArray::next(), et SplFixedArray::valid() ont été supprimées. A leur place, SplFixedArray::getIterator() a été ajoutée. Tout code qui utilise l'itération explicite sur SplFixedArray doit maintenant obtenir une valeur de Iterator à travers SplFixedArray::getIterator(). Cela signifie que SplFixedArray peut désormais être utilisé en toute sécurité dans les boucles imbriquées.

### Bibliothèque standard

- assert() n'évalue plus les arguments de type chaîne de caractères, ils sont traités comme n'importe quel autre argument. `assert($a == $b)` doit être utilisé à la place de `assert('$a == $b')`. La directive ini assert.quiet_eval et la constante `ASSERT_QUIET_EVAL` ont également été supprimées, car elles n'auraient plus d'effet.

- parse_str() ne peut plus être utilisé sans spécifier un tableau de résultats.

- Le filtre string.strip_tags a été supprimé.

- L'argument `needle` de strpos(), strrpos(), stripos(), strripos(), strstr(), strchr(), strrchr(), et stristr() sera désormais toujours interprété comme une chaîne de caractères. Auparavant, les `needle` étaient interprétés comme des points de code ASCII. Un appel explicite à chr() peut être utilisé pour rétablir le comportement précédent.

- L'argument `needle` pour strpos(), strrpos(), stripos(), strripos(), strstr(), stristr() et strrchr() peut désormais être vide.

- L'argument `length` pour substr(), substr_count(), substr_compare() et iconv_substr() peut désormais être `null`. Les valeurs `null` se comporteront comme si aucun argument de longueur n'avait été fourni et retourneront donc le reste de la chaîne de caractères au lieu d'une chaîne vide.

- L'argument `length` pour array_splice() peut maintenant être `null`. Les valeurs `null` se comporteront de la même manière que si l'on omettait l'argument, c'est-à-dire qu'elles supprimeront tout ce qui se trouve de l'`offset` à la fin du tableau.

- L'argument `args` de vsprintf(), vfprintf(), et vprintf() doit maintenant être un tableau. Auparavant n'importe quel type était accepté.

- L'option `'salt'` de password_hash() n'est plus supportée. Si l'option `'salt'` est utilisée, un avertissement est généré, le salt fourni est ignoré et un salt généré est utilisé à la place.

- La fonction quotemeta() retourne désormais une chaîne vide si une chaîne vide a été passée. Auparavant, elle retournait `false`.

- Les fonctions suivantes ont été supprimées :

  - hebrevc()
  - convert_cyr_string()
  - money_format()
  - ezmlm_hash()
  - restore_include_path()
  - get_magic_quotes_gpc()
  - get_magic_quotes_runtime()
  - fgetss()

- `FILTER_SANITIZE_MAGIC_QUOTES` a été supprimée.

- L'appel à implode() avec des paramètres dans l'ordre inverse `($pieces, $glue)` n'est plus supporté.

- parse_url() distingue désormais les requêtes et les fragments absents ou vides :

  - `http://example.com/foo → query = null, fragment = null`
  - `http://example.com/foo? → query = "", fragment = null`
  - `http://example.com/foo# → query = null, fragment = ""`
  - `http://example.com/foo?# → query = "", fragment = ""`
  Auparavant, dans tous les cas, la requête et le fragment étaient des `null`.

- var_dump() et debug_zval_dump() imprimeront maintenant les nombres à virgule flottante en utilisant serialize_precision plutôt que la précision. Dans une configuration par défaut, cela signifie que les nombres à virgule flottante sont désormais imprimés avec une précision totale par ces fonctions de débogage.

- Si le tableau retourné par __sleep() contient des propriétés inexistantes, celles-ci sont désormais ignorées de manière silencieuse. Auparavant, de telles propriétés auraient été sérialisées comme si elles avaient la valeur `null`.

- La locale par défaut au démarrage est désormais toujours `"C"`. Aucune locale n'est héritée de l'environnement par défaut. Auparavant, `LC_ALL` était réglé sur `"C"`, tandis que `LC_CTYPE` était hérité de l'environnement. Cependant, certaines fonctions ne respectaient pas les paramètres linguistiques hérités sans un appel explicite à setlocale(). Un appel explicite à setlocale() est désormais toujours nécessaire si un composant de locale doit être modifié par rapport à la valeur par défaut.

- La solution de repli DES dans crypt() a été supprimée. Si un format de salt inconnu est passé à crypt(), la fonction échouera avec `*0` au lieu de se rabattre sur un hachage DES faible.

- Spécifier des rounds hors plage pour SHA256/SHA512 crypt() échouera maintenant avec `*0` au lieu de se caler sur la limite la plus proche. Cela correspond au comportement de la glibc.

- Le résultat des fonctions de tri peut avoir changé, si le tableau contient des éléments qui se comparent comme étant égaux.

- Toutes les fonctions acceptant des fonctions de rappels qui ne sont pas explicitement spécifiées pour accepter des paramètres par référence seront désormais averties si une fonction de rappel avec des paramètres par référence est utilisée. Les exemples incluent array_filter() et array_reduce(). C'était déjà le cas pour la plupart des fonctions, mais pas toutes.

- L'enveloppe de flux HTTP utilisée par des fonctions telles que file_get_contents() annonce désormais HTTP/1.1 au lieu de HTTP/1.0 par défaut. Cela ne modifie pas le comportement du client mais les serveurs peuvent réagir différemment. Pour conserver l'ancien comportement, définissez l'option de contexte de flux `'protocol_version'`, par exemple

  `<?php
  $ctx = stream_context_create(['http' => ['protocol_version' => '1.0']]);
  echo file_get_contents('http://example.org', false, $ctx);
  ?>`

- L'appel à crypt() sans salt explicite n'est plus supporté. Si vous souhaitez produire un hachage fort avec un salt auto-généré, utilisez plutôt password_hash() à la place.

- substr(), mb_substr(), iconv_substr() et grapheme_substr() fixent désormais de manière cohérente les index hors limites à la limite de la chaîne de caractères. Auparavant, `false` était retourné au lieu de la chaîne vide dans certains cas.

- Sous Windows, les fonctions d'exécution de programmes(proc_open(), exec(), popen() etc.) utilisant l'interpréteur de commandes, exécutent désormais systématiquement %comspec% /s /c "$commandline", ce qui a le même effet que l'exécution de $commandline (sans les guillemets supplémentaires).

### Sysvsem

- Le paramètre `auto_release` de sem_get() a été modifié pour accepter les valeurs booléen au lieu de entier.

### Tidy

- Le paramètre `use_include_path`, qui n'était pas utilisé en interne, a été supprimé de tidy_repair_string().

- tidy::repairString() et tidy::repairFile() sont devenues des méthodes statiques.

### Tokenizer

- Les tokens `T_COMMENT` n'incluront plus de nouvelle ligne à la fin. La nouvelle ligne fera partie d'un jeton `T_WHITESPACE` suivant. Il convient de noter que `T_COMMENT` n'est pas toujours suivi d'un espace blanc, il peut également être suivi de `T_CLOSE_TAG` ou d'une fin de fichier.

- Les noms à espace de nommage sont désormais représentés à l'aide des attributs `T_NAME_QUALIFIED` `(Foo\Bar`), `T_NAME_FULLY_QUALIFIED``(\Foo\Bar`) et `T_NAME_RELATIVE``(namespace\Foo\Bar`). `T_NS_SEPARATOR` n'est utilisé que pour les séparateurs d'espace de noms autonomes, et n'est syntaxiquement valide qu'en conjonction avec les déclarations d'utilisation de groupe.

### XMLReader

XMLReader::open() et XMLReader::XML() sont désormais des méthodes statiques. Elles peuvent toujours être appelées en tant que méthodes d'instance, mais les classes qui en héritent doivent les déclarer comme statiques si elles surchargent ces méthodes.

### XML-RPC

L'extension XML-RPC a été déplacée vers PECL et ne fait plus partie de la distribution de PHP. et ne fait plus partie de la distribution de PHP.

### Zip

`ZipArchive::OPSYS_Z_CPM` a été supprimée (ce nom était une erreur de frappe). Utilisez plutôt `ZipArchive::OPSYS_CPM` à la place.

### Zlib

- gzgetss() a été supprimée.

- zlib.output_compression n'est plus automatiquement désactivée pour `Content-Type: image/*`.

### Packs de test PHP pour Windows

Le programme de test a été renommé de run-test.php à run-tests.php, pour correspondre à son nom dans php-src.