De nombreuses erreurs fatales et récupérables ont été converties en exceptions dans PHP 7. Ces exceptions d'erreur héritent de la classe Error, qui implémente elle-même l'interface Throwable (la nouvelle interface de base dont toutes les exceptions héritent).
Cela signifie que les gestionnaires d'erreurs personnalisés peuvent ne plus être déclenchés car des exceptions peuvent être levées à la place (provoquant de nouvelles erreurs irrécupérables pour les exceptions Error non interceptées).
Une description plus complète de la façon dont les erreurs fonctionnent en PHP 7 se trouve sur la page des erreurs PHP 7. Ce guide de migration énumérera simplement les modifications qui affectent la rétrocompatibilité.
Le code qui implémente un gestionnaire d'exceptions inscrit avec set_exception_handler() à l'aide d'une déclaration de type Exception provoquera une erreur fatale lorsqu'un objet Error est levé.
Si le gestionnaire doit fonctionner à la fois avec PHP 5 et 7, vous devriez supprimer la déclaration de type du gestionnaire, tandis que le code qui est migré pour travailler sur PHP 7 exclusivement peut simplement remplacer la déclaration de type Exception par Throwable.
<?php
// Code pour PHP 5 qui va se briser.
function handler(Exception $e) { ... }
set_exception_handler('handler');
// Compatible PHP 5 et 7.
function handler($e) { ... }
// PHP 7 seulement.
function handler(Throwable $e) { ... }
?>
Auparavant, certaines classes internes retournaient null
ou un objet
inutilisable lorsque le constructeur échouait. Toutes les classes internes
lèveront maintenant une Exception dans ce cas de la
même manière que les classes d'utilisateurs.
Les erreurs d'analyseur lèvent maintenant un objet ParseError.
La gestion des erreurs pour eval() doit maintenant inclure
un bloc catch
qui peut gérer cette erreur.
Tous les avis E_STRICT
ont été reclassés à d'autres niveaux.
La constante E_STRICT
est conservée, donc les appels comme
error_reporting(E_ALL|E_STRICT)
ne provoqueront pas d'erreur.
Situation | Nouveau niveau/comportement |
---|---|
Indexation par une ressource | E_NOTICE |
Méthodes statiques abstraites | Avis supprimé, ne déclenche aucune erreur |
"Redéfinir" un constructeur | Avis supprimé, ne déclenche aucune erreur |
Incompatibilité de signature pendant l'héritage | E_WARNING |
Même propriété (compatible) dans deux traits utilisés | Avis supprimé, ne déclenche aucune erreur |
Accès à une propriété statique non statiquement | E_NOTICE |
Seules les variables doivent être attribuées par référence | E_NOTICE |
Seules les variables doivent être transmises par référence | E_NOTICE |
Appel de méthodes non statiques statiquement | E_DEPRECATED |
PHP 7 utilise maintenant une arborescence de syntaxe abstraite lors de l'analyse des fichiers sources. Cela a permis de nombreuses améliorations à la langue qui étaient auparavant impossibles en raison des limitations dans l'analyseur utilisé dans les versions antérieures de PHP, mais a abouti à la suppression de quelques cas spéciaux pour des raisons de cohérence, qui a abouti à casser la rétro-compatibilité. Ces cas sont détaillés dans cette section.
L'accès indirect aux variables, propriétés et méthodes sera maintenant évalué strictement dans l'ordre de gauche à droite, par opposition à la combinaison précédente de cas spéciaux. Le tableau ci-dessous montre comment l'ordre d'évaluation a changé.
Expression | Interprétation PHP 5 | Interprétation PHP 7 |
---|---|---|
$$foo['bar']['baz']
|
${$foo['bar']['baz']}
|
($$foo)['bar']['baz']
|
$foo->$bar['baz']
|
$foo->{$bar['baz']}
|
($foo->$bar)['baz']
|
$foo->$bar['baz']()
|
$foo->{$bar['baz']}()
|
($foo->$bar)['baz']()
|
Foo::$bar['baz']()
|
Foo::{$bar['baz']}()
|
(Foo::$bar)['baz']()
|
Le code qui utilisait l'ancien ordre d'évaluation de droite à gauche doit être réécrit pour utiliser explicitement cet ordre d'évaluation avec des accolades (voir la colonne du milieu ci-dessus). Cela rendra le code compatible avec PHP 7.x et rétrocompatible avec PHP 5.x.
Cela affecte également le mot clé global
. La syntaxe des accolades
peut être utilisée pour émuler le comportement précédent si nécessaire :
<?php
function f() {
// Valide en PHP 5 uniquement.
global $$foo->bar;
// Valide en PHP 5 et 7.
global ${$foo->bar};
}
?>
list() assignera désormais des valeurs aux variables dans
l'ordre dans lequel elles sont définies, plutôt que dans l'ordre inverse. En
général, cela affecte uniquement le cas où list() est
utilisée en conjonction avec l'opérateur de tableau []
, comme
illustré ci-dessous :
<?php
list($a[], $a[], $a[]) = [1, 2, 3];
var_dump($a);
?>
Résultat de l'exemple ci-dessus en PHP 5 :
array(3) { [0]=> int(3) [1]=> int(2) [2]=> int(1) }
Résultat de l'exemple ci-dessus en PHP 7 :
array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
En général, il est recommandé de ne pas compter sur l'ordre dans lequel les affectations de la fonction list() se produisent, car il s'agit d'un détail d'implémentation qui peut changer à nouveau à l'avenir.
Les constructions de list() ne peuvent plus être vides. Les éléments suivants ne sont plus autorisés :
<?php
list() = $a;
list(,,) = $a;
list($x, list(), $y) = $a;
?>
list() ne peut plus défaire les variables de chaîne de caractères. str_split() devrait être utilisé à la place.
L'ordre des éléments dans un tableau a changé lorsque ces éléments ont été créés automatiquement en les référençant dans une assignation par référence. Par exemple :
<?php
$array = [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
?>
Résultat de l'exemple ci-dessus en PHP 5 :
array(2) { ["b"]=> &int(1) ["a"]=> &int(1) }
Résultat de l'exemple ci-dessus en PHP 7 :
array(2) { ["a"]=> &int(1) ["b"]=> &int(1) }
En PHP 5, l'utilisation de parenthèses redondantes autour d'un argument de fonction peut calmer les avertissements de normes strictes lorsque l'argument de fonction a été passé par référence. L'avertissement est maintenant toujours émis.
<?php
function getArray() {
return [1, 2, 3];
}
function squareArray(array &$a) {
foreach ($a as &$v) {
$v **= 2;
}
}
// Generates a warning in PHP 7.
squareArray((getArray()));
?>
L'exemple ci-dessus va afficher :
Notice: Only variables should be passed by reference in /tmp/test.php on line 13
foreach
Des changements mineurs ont été faits sur le comportement de
la structure de contrôle foreach
, principalement sur la gestion
du pointeur interne de tableau et la modification du tableau étant parcouru.
foreach
ne modifie plus le pointeur interne de tableau
Antérieur à PHP 7, le pointeur interne de tableau était modifié pendant
qu'un tableau était parcouru avec foreach
. Cela n'est plus le cas,
comme le montre l'exemple suivant :
<?php
$array = [0, 1, 2];
foreach ($array as &$val) {
var_dump(current($array));
}
?>
Résultat de l'exemple ci-dessus en PHP 5 :
int(1) int(2) bool(false)
Résultat de l'exemple ci-dessus en PHP 7 :
int(0) int(0) int(0)
foreach
par valeur travaille sur une copie du tableau
Lors de l'utilisation du mode par défaut (par valeur), foreach
travaille maintenant sur une copie du tableau en cours parcouru
plutôt que sur le tableau lui-même. Cela signifie que les changements
réalisés sur le tableau pendant son parcours n'affecteront pas les
valeurs qui sont parcourues.
foreach
par référence a été amélioré
Lors du parcours d'un tableau par référence, foreach
identifie
mieux les changements faits au tableau pendant son parcours. Par exemple,
si des valeurs sont ajoutées à un tableau pendant son parcours, alors ces
nouvelles valeurs seront également parcourues :
<?php
$array = [0];
foreach ($array as &$val) {
var_dump($val);
$array[1] = 1;
}
?>
Résultat de l'exemple ci-dessus en PHP 5 :
int(0)
Résultat de l'exemple ci-dessus en PHP 7 :
int(0) int(1)
Le parcours d'un objet non-Traversable est maintenant identique au parcours d'un tableau par référence. En conséquence l'amélioration du comportement lors de la modification d'un tableau pendant son parcours est également appliquée lorsque des propriétés sont ajoutées ou supprimées d'un objet.
Auparavant, les littéraux octaux qui contenaient des nombres non valides
étaient tronqués silencieusement (0128
a été pris comme
012
). Désormais, un littéral octal non valide provoquera
une erreur d'analyse.
Les décalages de bits par nombres négatifs vont maintenant lancer une ArithmeticError:
<?php
var_dump(1 >> -1);
?>
Résultat de l'exemple ci-dessus en PHP 5 :
int(0)
Résultat de l'exemple ci-dessus en PHP 7 :
Fatal error: Uncaught ArithmeticError: Bit shift by negative number in /tmp/test.php:2 Stack trace: #0 {main} thrown in /tmp/test.php on line 2
Les décalages de bits (dans les deux sens) au-delà de la largeur de bit d'un entier retourneront toujours 0. Auparavant, le comportement de ces décalages était dépendant de l'architecture.
Auparavant, lorsque 0 a été utilisé comme diviseur pour les opérateurs de
division (/) ou de modulo (%), un E_WARNING était émis et false
était retourné. Désormais, l'opérateur de division retourne un float en tant
que +INF,-INF ou NAN, comme spécifié par IEEE 754. Le E_WARNING de l'opérateur
de modulo a été supprimé et lèvera une exception DivisionByZeroError.
<?php
var_dump(3/0);
var_dump(0/0);
var_dump(0%0);
?>
Résultat de l'exemple ci-dessus en PHP 5 :
Warning: Division by zero in %s on line %d bool(false) Warning: Division by zero in %s on line %d bool(false) Warning: Division by zero in %s on line %d bool(false)
Résultat de l'exemple ci-dessus en PHP 7 :
Warning: Division by zero in %s on line %d float(INF) Warning: Division by zero in %s on line %d float(NAN) PHP Fatal error: Uncaught DivisionByZeroError: Modulo by zero in %s line %d
Les chaîne de caractères contenant des nombres hexadécimaux ne sont plus considérées comme numériques. Par exemple :
<?php
var_dump("0x123" == "291");
var_dump(is_numeric("0x123"));
var_dump("0xe" + "0x1");
var_dump(substr("foo", "0x1"));
?>
Résultat de l'exemple ci-dessus en PHP 5 :
bool(true) bool(true) int(15) string(2) "oo"
Résultat de l'exemple ci-dessus en PHP 7 :
bool(false) bool(false) int(0) Notice: A non well formed numeric value encountered in /tmp/test.php on line 5 string(3) "foo"
filter_var() peut être utilisé pour vérifier si une chaîne de caractères contient un nombre hexadécimal, et aussi pour convertir une chaîne de caractères de ce type en un entier :
<?php
$str = "0xffff";
$int = filter_var($str, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);
if (false === $int) {
throw new Exception("Invalid integer!");
}
var_dump($int); // int(65535)
?>
\u{
peut provoquer des erreurs
En raison de l'ajout de la nouvelle
syntaxe
d'échappement du point de code Unicode, les chaîne de caractères contenant un littéral
\u{
suivi d'une séquence non valide provoquera une erreur fatale.
Pour éviter cela, la barre oblique inverse principale doit être échappée.
Ces fonctions ont été dépréciées en PHP 4.1.0 en faveur de
call_user_func() et
call_user_func_array(). Vous pourriez également utiliser les
fonctions variables
et/ou l'opérateur
...
.
Toutes les fonctions ereg
ont été supprimées.
PCRE est une alternative recommandée.
La fonction obsolète mcrypt_generic_end() a été remplacée par mcrypt_generic_deinit().
De plus, les fonctions obsolètes mcrypt_ecb(),
mcrypt_cbc(), mcrypt_cfb() et
mcrypt_ofb() ont été remplacées par l'utilisation de
mcrypt_decrypt() avec la constante appropriée
MCRYPT_MODE_*
.
Toutes les fonctions ext/mysql ont été supprimées. Pour plus d'informations sur le choix d'une autre API MySQL, consultez choisir une API MySQL.
Toutes les fonctions ext/mssql
ont été supprimées.
Les alias obsolètes datefmt_set_timezone_id() et IntlDateFormatter::setTimeZoneID() ont été supprimés et remplacés respectivement par datefmt_set_timezone() et IntlDateFormatter::setTimeZone().
set_magic_quotes_runtime(), ainsi que son alias magic_quotes_runtime(), ont été supprimées. Elles étaient obsolètes à partir PHP 5.3.0, et sans effet depuis la suppression des guillemets magiques en PHP 5.4.0.
L'alias obsolète set_socket_blocking() a été supprimé et remplacé par stream_set_blocking().
dl() ne peut plus être utilisé avec PHP-FPM. Il continue à fonctionner dans les SAPIs CLI et Embed.
Le support des polices PostScript Type1 a été supprimé de l'extension GD, entraînant la suppression des fonctions suivantes :
À la place, il est recommandé d'utiliser les polices TrueType et leurs fonctions associées.
Les directives INI suivantes ont été supprimées car leurs fonctionnalités associées ont également été supprimées:
always_populate_raw_post_data
asp_tags
xsl.security_prefs
La directive xsl.security_prefs
a été supprimée.
Au lieu de cela, la méthode XsltProcessor::setSecurityPrefs()
doit être appelée pour contrôler les préférences de sécurité sur une
base du processeur.
Le résultat de l'instruction new
ne peut plus être assigné à une variable
par référence :
<?php
class C {}
$c =& new C;
?>
Résultat de l'exemple ci-dessus en PHP 5 :
Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3
Résultat de l'exemple ci-dessus en PHP 7 :
Parse error: syntax error, unexpected 'new' (T_NEW) in /tmp/test.php on line 3
Les noms suivants ne peuvent pas être utilisés pour nommer des classes, des interfaces ou des traits :
En outre, les noms suivants ne doivent pas être utilisés. Bien qu'ils ne génèrent pas une erreur dans PHP 7.0, ils sont réservés pour une utilisation future et doivent être considérés comme obsolètes.
La prise en charge de l'utilisation des balises ASP et script pour délimiter le code PHP a été supprimée. Les balises affectées sont :
Balise d'ouverture | Balise de fermeture |
---|---|
<% |
%> |
<%= |
%> |
<script language="php"> |
</script> |
Précédemment déconseillé dans PHP 5.6,
les appels statiques effectués à une méthode non statique avec un contexte
incompatible se traduiront désormais par la méthode appelée ayant une variable
$this
non définie et un avertissement d'obsolescence est émis.
<?php
class A {
public function test() { var_dump($this); }
}
// Note: Does NOT extend A
class B {
public function callNonStaticMethodOfA() { A::test(); }
}
(new B)->callNonStaticMethodOfA();
?>
Résultat de l'exemple ci-dessus en PHP 5.6 :
Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8 object(B)#1 (0) { }
Résultat de l'exemple ci-dessus en PHP 7 :
Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8 Notice: Undefined variable: this in /tmp/test.php on line 3 NULL
yield
est maintenant un opérateur associatif à droite
La construction yield
ne nécessite plus de parenthèses et a été remplacée
par un opérateur associatif droit avec la priorité entre print
et =>
. Cela peut entraîner un changement de comportement :
<?php
echo yield -1;
// A été précédemment interprété comme
echo (yield) - 1;
// Et est maitenant interprété comme
echo yield (-1);
yield $foo or die;
// A été précédemment interprété comme
yield ($foo or die);
// Et est maitenant interprété comme
(yield $foo) or die;
?>
Les parenthèses peuvent être utilisées pour lever l'ambiguïté sur ces cas.
Il n'est plus possible de définir deux ou plusieurs paramètres de fonction
avec le même nom. Par exemple, la fonction suivante déclenchera un
E_COMPILE_ERROR
:
<?php
function foo($a, $b, $unused, $unused) {
//
}
?>
func_get_arg(), func_get_args(), debug_backtrace() et les traces d'exception ne signalent plus la valeur d'origine qui a été passée à un paramètre, mais fourniront plutôt la valeur actuelle (qui aurait pu être modifiée).
<?php
function foo($x) {
$x++;
var_dump(func_get_arg(0));
}
foo(1);?>
Résultat de l'exemple ci-dessus en PHP 5 :
1
Résultat de l'exemple ci-dessus en PHP 7 :
2
Il n'est plus possible de définir deux ou plusieurs blocs par défaut dans
une instruction switch. Par exemple, l'instruction switch suivante déclenchera
un E_COMPILE_ERROR
:
<?php
switch (1) {
default:
break;
default:
break;
}
?>
$HTTP_RAW_POST_DATA n'est plus disponible. Le flux
php://input
doit être utilisé à la place.
#
dans le fichier INI ont été supprimés
La prise en charge des commentaires avec le préfix #
dans
les fichiers INI a été supprimée. ;
(point-virgule) doit être
utilisé à la place. Cette modification s'applique aux php.ini, ainsi qu'aux
fichiers gérés par parse_ini_file() et
parse_ini_string().
L'extension JSON a été remplacée par JSOND, provoquant trois incompatibilités
BC mineures. Premièrement, un nombre ne doit pas se terminer par une virgule
décimale (c.-à-d. 34.
doit être modifié en 34.0
ou en 34
). Deuxièmement, lors de l'utilisation de la notation
scientifique, l'exposant e
ne doit pas suivre immédiatement un
point décimal (c.-à-d. 3.e3
doit être modifié soit en
3.0e3
ou en 3e3
). Enfin, une chaîne vide n'est
plus considérée comme du JSON valide.
Auparavant, les fonctions internes devaient tronquer silencieusement les nombres
produits à partir de contraintes de type float à entier lorsque le nombre était
trop volumineux pour représenter un entier. Désormais, un E_WARNING sera émis
et null
sera renvoyé.
Toutes les fonctions de prédicat implémentées par des gestionnaires de session
personnalisés qui retournent false
ou -1
seront des erreurs
fatales. Si une valeur de ces fonctions autre qu'un booléen, -1
ou 0
est retournée, elle échouera et un E_WARNING sera émis.
L'algorithme de tri interne a été amélioré, ce qui peut entraîner un ordre de tri différent des éléments, qui se comparent comme égaux auparavant.
Note:
Ne comptez pas sur l'ordre des éléments qui se comparent comme égaux; il pourrait changer à tout moment.
Les instructions break
et continue
en dehors
d'une boucle ou d'une structure de contrôle switch
sont
maintenant détectées au moment de la compilation au lieu de l'exécution comme
avant, et déclenchent un E_COMPILE_ERROR
.
Les instructions break
et continue
ne permettent plus
que leur argument soit une constante, et déclenchent une
E_COMPILE_ERROR
.
L'extension mhash a été entièrement intégrée dans l'extension Hash. Par conséquent, il n'est plus possible de détecter le support mhash avec extension_loaded(); utiliser function_exists() à la place. En outre, mhash n'est plus rapporté par get_loaded_extensions() et les fonctionnalités connexes.
La directive declare(ticks) ne fuit plus dans des unités de compilation différentes.