PHP 8.4.2 Released!

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.

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

Exif

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

Filter

GD

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

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

MBString

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

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)

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 :

  • 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

Tidy

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

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.

add a note

User Contributed Notes 2 notes

up
20
retry, abort, fail
2 years ago
The change in string to int comparison mentioned above (e.g. '' == 0 now equates to false) has some other nasty consequences:

$a = '';

// php 8

if ( $a < 0 ) echo 'true'; // echos true
if ( $a < -1) echo 'true'; // echos true
if ( $a < -100 ) echo 'true'; // echos true

// php 7

if ( $a < 0 ) echo 'true'; // no output
if ( $a < -1) echo 'true'; // no output
if ( $a < -100 ) echo 'true'; // no output

So in a situation where you may have a web form input and expected an empty value to equate to 0, watch out not only for == 0, != 0, and <= 0 comparisons, but ALL < or <= comparisons to negative integers.
up
1
aphpguy at galaxy dot za dot net
1 year ago
If you have older projects that break with PHP7 to 8 migration due to the loose comparison issue:

i.e. if ($a == 0) different behaviour between PHP 7 and PHP 8
(for case like $a = "" or $a = "123foo" and other cases listed at top)

replace in old code:

if ($a == 0) { .. }

with

if (cmp_eq($a, $b)) { .. }

Tested with a wide range of scenarios, even against arrays, booleans, file handles, pipe handles, objects, scalars and numbers.

So old code still behave like before.
Then both PHP8.x and older PHP up to ver 7.x will give the exact same boolean true or false output for loose comparisons.

function cmp_eq($a, $b) {
// If both $a and $b are of type strings, compare them as strings
if (is_string($a) && is_string($b)) { return $a == $b; } // may not be === because php says '42' equals '042' true yet '42' === '042' is false.

// If both $a and $b are numeric strings, compare them as numbers
if (is_numeric($a) && is_numeric($b)) { return $a == $b; }

// If $a is an empty string and $b is 0, or vice versa, return true
if (($a === '' && $b === 0) || ($a === 0 && $b === '')) { return true; }

// If $a is a non-numeric string and $b is 0, or vice versa, return true
if ((is_string($a) && ($a !== '') && ($b === 0)) || (($a === 0) && is_string($b) && ($b !== ''))) {
return true;
}
// special case '123abc' == 123 .. php 7 casts 123abc to 123, then 123 == 123 results in true. lets mimic that.
if ((is_string($a) && ($a !== '') && (is_numeric($b)) && ((bool)$b))) {
$number = filter_var($a, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); //"-234.56xyz"
return $number == $b;
}
if (is_numeric($a) && ((bool)$a) && is_string($b) && ($b !== '')) {
$number = filter_var($b, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); //"-234.56xyz"
return $a == $number;
}

// If $a is a number and $b is a non-numeric string, cast $a to string and compare
if (is_numeric($a) && is_string($b)) { return strval($a) == $b; }

// If $b is a number and $a is a non-numeric string, cast $b to string and compare
if (is_string($a) && is_numeric($b)) { return $a == strval($b); }

// If $a and $b are both non-numeric strings, compare them directly, we should return true if they are the same
return $a == $b;
} // end func cmp_eq

Note: the better way would be to port code to PHP 8, use strict variable typing and rather make use of the === and !== operators.

But in some cases having lots of old code to quickly patch, this might help.
To Top