Les boucles foreach par référence peuvent désormais visiter des éléments précédemment ignorés après le compactage d'un tableau. Les pointeurs internes sur des éléments supprimés passent désormais à l'élément survivant suivant lors de la copie sur écriture.
?? et empty() sur une propriété
magique n'appellent plus __get() lorsque
__isset() a matérialisé la propriété
en écrivant dans la table des propriétés.
La valeur fraîchement écrite est retournée directement.
isset() appliqué directement à la propriété n'est pas
affecté ; les formes imbriquées telles que
isset($o->p['k']) suivent le même chemin que
??.
<?php
#[\AllowDynamicProperties]
class Example
{
public function __isset(string $name): bool
{
$this->$name = 'from __isset()';
return true;
}
public function __get(string $name): string
{
return 'from __get()';
}
}
$example = new Example();
var_dump($example->foo ?? 'default');
// À partir de PHP 8.6.0 : string(14) "from __isset()"
// Avant PHP 8.6.0 : string(12) "from __get()"array_intersect() avec au moins deux tableaux convertit désormais les valeurs en chaînes lors du parcours de ses entrées plutôt que pendant les comparaisons du tri. Cela peut modifier le nombre et l'ordre des avertissements de conversion et des appels à __toString(), l'exception de conversion qui est atteinte, ainsi que le résultat pour les implémentations de __toString() à état. Les types des arguments sont validés avant de vérifier la présence de tableaux vides ou de convertir les valeurs ; un argument ultérieur invalide peut donc supprimer les effets de bord de conversion des tableaux précédents. Les valeurs ne sont pas converties si l'un des tableaux d'entrée est vide.
Le saut de page (\f) est désormais ajouté aux
caractères supprimés par défaut par trim(),
rtrim() et ltrim().
<?php
var_dump(trim("\f hello \f"));
// À partir de PHP 8.6.0 : string(5) "hello"
// Avant PHP 8.6.0 : string(9) "\f hello \f"Les fonctions suivantes lèvent désormais une ValueError lorsqu'une valeur de drapeau ou de mode invalide est passée :
mode)case)flags)sorting_order)
Les fonctions suivantes lèvent désormais une
ValueError lorsque l'argument donné contient
des octets NUL :
extension_filename)prefix)string)cwd)Les fonctions suivantes lèvent désormais une ValueError pour les valeurs hors limites, au lieu de les plafonner silencieusement ou de les laisser déborder :
decimals
est en dehors de la plage des entiers.
seconds est
supérieur à UINT_MAX, ou
UINT_MAX / 1000 sous Windows.
microseconds
est supérieur à UINT_MAX.
linkinfo() lève désormais une
ValueError lorsque l'argument
path est vide.
setlocale() lève désormais une
ValueError lorsqu'un nom de locale contient
des octets NUL, au lieu de le tronquer silencieusement.
Les tableaux ne sont désormais acceptés que pour l'argument
locales.
Passer un tableau comme argument de locale variadique ultérieur lance
désormais une TypeError.
Passer des arguments de locale supplémentaires lorsque
locales est un tableau lance désormais une
ArgumentCountError.
Les fonctions suivantes lèvent désormais une
ValueError lorsque l'argument
filename contient des octets NUL :
base_convert(), bindec(), hexdec() et octdec() émettent désormais une notice lorsqu'elles ne peuvent pas convertir précisément le nombre donné.
unpack() interprète désormais un <
ou un > suivant immédiatement un code de format
comme un modificateur d'endianness, et non comme le premier caractère du
nom de l'élément.
Les formats tels que "s<value" produisent désormais
la clé "value" au lieu de
"<value", et "C>name" lève une
ValueError car le code de format
C n'accepte aucun modificateur d'endianness.
Un nom commençant par ces caractères n'est pas affecté lorsqu'un
répéteur le précède, comme dans "s1<value".
Voir aussi les
nouveaux
modificateurs d'endianness.
<?php
var_dump(unpack('s<value', "\x01\x00"));
// À partir de PHP 8.6.0 : ["value" => 1]
// Avant PHP 8.6.0 : ["<value" => 1]Il n'est plus possible de cloner des objets variant, car le comportement du clonage était mal défini.
La fonction de rappel enregistrée avec
CURLOPT_READFUNCTION lance désormais une
ValueError lorsqu'elle retourne un entier
autre que 0,
CURL_READFUNC_ABORT ou
CURL_READFUNC_PAUSE.
Les propriétés précédemment documentées comme en lecture seule (par ex.
DOMNode::$nodeType,
DOMDocument::$xmlEncoding,
DOMEntity::$actualEncoding,
DOMEntity::$encoding,
DOMEntity::$version) sont désormais déclarées avec une
visibilité
asymétrique (public private(set)).
Toute tentative d'écriture depuis l'extérieur de la classe lève désormais
Cannot modify private(set) property class::$prop from global scope
au lieu de l'ancienne erreur de modification d'une propriété en lecture
seule.
ReflectionProperty::isWritable() rapporte également
ces propriétés avec exactitude.
L'accès par index sur les objets Dom\DtdNamedNodeMap
retourne désormais null pour les index entiers négatifs au lieu de
retourner le premier nœud, et lève une
ValueError lorsque l'index entier est
supérieur à PHP_INT_MAX au lieu de déborder vers un
index plus petit.
ftp_nb_fget(), ftp_nb_fput(),
ftp_nb_get() et ftp_nb_put() lancent
désormais une Error lorsque la connexion est
déjà en cours de transfert, au lieu d'émettre un avertissement et de
retourner false.
ftp_close() lance déjà une exception dans la même
situation.
imagesetstyle(), imagefilter() et imagecrop() filtrent les types et les valeurs de leurs arguments de type tableau et lèvent en conséquence une TypeError ou une ValueError.
imageaffinematrixget() impose désormais le type
array|float documenté
pour le paramètre options, y compris le
comportement correspondant du typage faible et strict.
gmp_fact() lève désormais une
ValueError si num
ne tient pas dans un unsigned long.
gmp_pow(), gmp_binomial(), gmp_root() et gmp_rootrem() lèvent désormais une ValueError si leur second argument ne tient pas dans un unsigned long.
Les opérateurs de décalage (<<,
>>) et d'exponentiation (**)
sur les objets GMP lèvent désormais une
ValueError lorsque les opérandes de droite
GMP sont en dehors de la plage des unsigned long, au
lieu de les tronquer silencieusement.
L'analyse des chaînes d'entiers GMP lève désormais
une ValueError pour les chaînes contenant des
octets NUL, au lieu de les tronquer silencieusement.
Le message de la DivisionByZeroError levée
par gmp_powm() lors d'un modulo par zéro inclut
désormais le nom de la fonction et l'index de l'argument
(modulus).
Passer un objet non stringable comme fuseau horaire aux API Intl qui acceptent des objets ou des chaînes de fuseau horaire lève désormais une TypeError au lieu d'une Error.
IntlIterator::current() retourne désormais null
lorsqu'elle est appelée avant que l'itérateur ne soit positionné, ou après
que l'itérateur est devenu invalide, au lieu d'exposer une valeur indéfinie.
IntlBreakIterator::getLocale() lève désormais une
ValueError lorsque le type n'est ni
Locale::ACTUAL_LOCALE ni
Locale::VALID_LOCALE, au lieu de retourner false.
MessageFormatter::parse() et
MessageFormatter::parseMessage() retournent désormais
PHP_INT_MIN sous forme de int, plutôt que
de float, sur les plateformes 64 bits lors de l'analyse de
valeurs entières.
Le paramètre type de
IntlBreakIterator::getPartsIterator() est passé de
string à int pour correspondre à l'implémentation
sous-jacente.
UConverter::transcode() rejette désormais les valeurs
d'option from_subst et to_subst de plus
de 127 octets, au lieu de tronquer silencieusement la longueur avant de la
transmettre à ICU.
ResourceBundle::get() et
resourcebundle_get() rapportent désormais les recherches
de ressources sans repli avec
without fallback to locale
au lieu du message mal formé
without fallback from to locale
.
IntlDateFormatter::parse()/datefmt_parse()
et
IntlDateFormatter::localtime()/datefmt_localtime()
lèvent désormais une TypeError lorsque
l'argument offset n'est pas de type int,
au lieu de convertir silencieusement la valeur.
Collator::sort(),
collator_sort(),
Collator::asort() et
collator_asort() rapportent désormais les échecs de
conversion UTF-8/UTF-16 pendant la
comparaison via le mécanisme d'erreur d'intl et retournent false.
Avec intl.use_exceptions
activé, ces échecs lancent une IntlException.
Auparavant, ces chemins émettaient un avertissement et comparaient la
valeur comme une chaîne vide.
Les tables de données Unicode ont été mises à jour vers Unicode 18.0.
pcntl_alarm() lève désormais une
ValueError si l'argument
seconds est inférieur à zéro ou supérieur à la
valeur UINT_MAX de la plateforme.
pcntl_exec() lève désormais une
ValueError si l'argument
args n'est pas un tableau de type liste.
preg_grep() retourne désormais false au lieu d'un
tableau partiel lorsqu'une erreur d'exécution PCRE se
produit (par ex. une entrée UTF-8 malformée avec le
modificateur u).
Cela est cohérent avec les autres fonctions preg_*.
Lorsque pg_fetch_object() reçoit un paramètre
constructor_args non vide pour une classe sans
constructeur, la ValueError fait désormais
référence à l'argument constructor_args au lieu de
class.
Les erreurs levées lorsque la classe demandée n'est pas instanciable
(abstraite, interface, énumération) apparaissent désormais avant la
récupération de la ligne.
Phar::mungServer() lève désormais une ValueError lorsqu'une valeur d'argument invalide est passée, au lieu de l'ignorer silencieusement.
Phar::addEmptyDir() rejette désormais les chemins
"/.phar" en plus des chemins ".phar",
et lève la même BadMethodCallException pour
les tentatives de création du répertoire magique réservé
".phar" par cette forme.
Les noms non magiques qui partagent simplement le préfixe
".phar" sont désormais traités comme des répertoires
ordinaires.
Les fichiers ne sont automatiquement interprétés comme des archives Phar
lors de leur inclusion que si ".phar" apparaît comme
extension dans la composante nom de fichier de leur chemin.
Auparavant, cela pouvait se produire dans un nom de répertoire ou comme
partie d'une extension telle que ".pharma".
Définir session.cookie_path,
session.cookie_domain ou
session.cache_limiter avec
une valeur contenant des octets NUL émet désormais un
avertissement et laisse le réglage inchangé.
Auparavant, les octets NUL étaient silencieusement
acceptés : pour cookie_path et
cookie_domain, cela amenait la SAPI à
abandonner l'en-tête Set-Cookie ; pour
cache_limiter, la valeur était silencieusement tronquée
à l'octet NUL.
session_module_name() lance désormais une
ValueError si name
est une chaîne contenant des octets NUL.
session_encode() retourne désormais une chaîne vide au
lieu de false pour les sessions vides.
Elle ne retourne désormais false que lorsque les données de session n'ont
pas pu être encodées.
Cela se produit principalement avec le gestionnaire de sérialisation par
défaut si une clé contient le caractère pipe (|).
Lorsque session.lazy_write
est activé et qu'un gestionnaire de session implémente
SessionUpdateTimestampHandlerInterface, les
sessions qui ont été lues comme vides et restent vides au moment de
l'écriture déclenchent désormais
SessionUpdateTimestampHandlerInterface::updateTimestamp()
au lieu de SessionHandlerInterface::write().
Auparavant, SessionHandlerInterface::write() était
toujours appelée pour les sessions vides car
session_encode() retournait false, contournant la
comparaison de lazy_write.
Les gestionnaires de session personnalisés qui s'appuient sur l'appel de
SessionHandlerInterface::write() avec des données
vides (par ex. pour détruire la session) devraient implémenter la même
logique dans leur méthode
SessionUpdateTimestampHandlerInterface::updateTimestamp().
Les valeurs par défaut de trois réglages INI de session ont changé afin de fournir un comportement sécurisé dès l'installation :
1 (auparavant 0).
Le mode strict rejette les identifiants de session non initialisés, ce
qui atténue la fixation de session.
Les gestionnaires de session personnalisés qui s'appuyaient auparavant sur
l'acceptation d'identifiants fournis de l'extérieur sans entrée de
stockage correspondante doivent soit implémenter
SessionUpdateTimestampHandlerInterface::validateId()
et SessionIdInterface::create_sid(), soit
définir explicitement ce réglage à 0.
1 (auparavant 0).
Les cookies de session ne sont plus accessibles à JavaScript via
document.cookie.
Les applications qui lisent le cookie de session depuis JavaScript doivent
définir explicitement ce réglage à 0.
"Lax" (auparavant non défini).
Les cookies de session ne sont plus envoyés lors des requêtes
inter-sites autres que les navigations de premier niveau utilisant des
méthodes HTTP sûres.
Les applications qui dépendent de l'envoi des cookies de session lors de
soumissions POST inter-sites doivent définir explicitement ce réglage à
"None" (et définir également
session.cookie_secure
à 1).
SessionHandler::validateId() a été ajoutée et
délègue au gestionnaire de sauvegarde configuré.
Une sous-classe qui déclare SessionHandler::validateId()
sans type de retour émet désormais un avertissement de dépréciation pour le
type de retour bool provisoire.
Une sous-classe qui surcharge SessionHandler::open()
sans appeler parent::open() conserve son comportement
précédent et émet un avertissement lorsqu'un identifiant est validé.
shmop_open() lève désormais une
ValueError lorsque l'argument
key est en dehors de la plage key_t
de la plateforme, au lieu de transmettre une clé tronquée au système
d'exploitation.
SimpleXMLElement::__construct() lève désormais une
ValueError lorsque l'argument
data contient des octets NUL,
comme simplexml_load_file().
Avec dataIsURL défini, le chemin était auparavant
tronqué au premier octet NUL.
Sans lui, la chaîne était transmise à libxml, qui, avec les options par
défaut, rejette un NUL sur les versions actuelles mais
accepte le document tronqué sur les versions plus anciennes et avec
LIBXML_RECOVER.
L'option "classmap" de
SoapClient et SoapServer
rejette désormais les tableaux contenant des clés entières.
Auparavant, les tableaux creux à clés entières et les tableaux à clés
mixtes pouvaient être acceptés.
SoapClient lance désormais une
TypeError pour les options
"classmap" qui ne sont pas des tableaux et une
ValueError pour les tableaux contenant des
clés entières, y compris lorsque l'option "exceptions"
est désactivée.
L'analyse des WSDL/schémas XML rejette
désormais les valeurs entières hors limites pour les contraintes
d'occurrence et les facettes de restriction entières.
Les valeurs négatives de minOccurs et
maxOccurs sont également rejetées.
Les erreurs d'encodage SOAP rapportent désormais le type concerné ou
l'opération défaillante dans le message d'erreur, au lieu du message
générique Encoding: Violation of encoding rules
.
Le code qui compare le message exact peut nécessiter une mise à jour.
socket_set_option() avec
SO_ATTACH_REUSEPORT_CBPF nécessite désormais une
value de type int et un
level égal à SOL_SOCKET.
Tout autre type de valeur lance une TypeError
au lieu d'être converti, et tout autre niveau émet un avertissement et
retourne false.
socket_set_option() avec
SO_ATTACH_REUSEPORT_CBPF et une
value égale à 0 détache désormais
le filtre reuseport via SO_DETACH_REUSEPORT_BPF.
Elle utilisait auparavant SO_DETACH_BPF, un alias de
SO_DETACH_FILTER, qui laissait le programme reuseport
attaché.
Les fonctions de hachage de mots de passe
sodium_crypto_pwhash(),
sodium_crypto_pwhash_str(),
sodium_crypto_pwhash_scryptsalsa208sha256() et
sodium_crypto_pwhash_scryptsalsa208sha256_str() lancent
désormais une ValueError au lieu d'une
SodiumException lorsqu'un argument est hors
limites, comme un opslimit ou un
memlimit inférieur au minimum documenté.
SodiumException est toujours lancée pour les
échecs internes de libsodium.
Les implémentations de SplObjectStorage::getHash() ne peuvent plus modifier aucune instance de SplObjectStorage. Toute tentative en ce sens lance désormais une Error.
SplFileObject::next() fait désormais avancer le flux lorsqu'aucun appel précédent à SplFileObject::current() n'a mis une ligne en cache. Un appel ultérieur à SplFileObject::current() retourne la nouvelle ligne plutôt que la précédente.
SplFileObject::fgets() ne met plus en cache la ligne retournée pour les appels ultérieurs à SplFileObject::current(). SplFileObject::current() relit désormais depuis la position courante du flux au lieu de retourner la ligne que SplFileObject::fgets() vient de retourner.
SplFileObject::next() au-delà de la fin du fichier (EOF) n'incrémente plus SplFileObject::key() sans limite. SplFileObject::seek() au-delà de EOF produit désormais la même valeur de SplFileObject::key() que SplTempFileObject ; les deux retournaient auparavant des valeurs différentes.
DirectoryIterator::key() retourne désormais int|string, et DirectoryIterator::current() retourne string|SplFileInfo|static.
shm_attach() lève désormais une
ValueError lorsque l'argument
key est en dehors de la plage key_t
de la plateforme, au lieu de transmettre une clé tronquée au système
d'exploitation.
Uri\WhatWg\Url::__construct() définit désormais
softErrors à un tableau vide lorsque le traitement
de l'URL lance une exception, au lieu de conserver sa valeur.
Les erreurs de validation de l'URL restent disponibles dans la propriété
Uri\WhatWg\InvalidUrlException::$errors.
Uri\WhatWg\Url::__construct(),
Uri\WhatWg\Url::parse(), les méthodes
Uri\WhatWg\Url::with*() et
Uri\WhatWg\UrlBuilder::build() rapportent désormais
les erreurs de validation dans l'ordre où elles sont détectées.
Cela inverse l'ordre de plusieurs erreurs par rapport à PHP 8.5.
ZipArchive::extractTo() lève désormais une
TypeError pour l'argument
files si une ou plusieurs des entrées ne sont pas
des chaînes.
ZipArchive::addGlob() et
ZipArchive::addPattern() lèvent désormais une
TypeError lorsque l'option
"remove_all_path" n'est pas de type bool,
ou lorsque les options "comp_method",
"comp_flags" ou "enc_method" ne sont
pas de type int (les chaînes numériques sont converties), au
lieu d'émettre un avertissement.
Sérialiser ou désérialiser une ZipArchive lance désormais une Exception. Une sous-classe peut surcharger __serialize() et __unserialize() pour effectuer un aller-retour via ZipArchive::closeString() et ZipArchive::openString().
deflate_init() lève désormais une
TypeError lorsque la valeur de l'option
"level", "memory",
"window" ou "strategy" n'est pas de
type int.
inflate_init() lève désormais une
TypeError lorsque la valeur de l'option
"window" n'est pas de type int.