The 7th Annual China PHP Conference

Modifications entrainant une incompatibilité ascendante

Modifications apportées à la gestion des erreurs et des exceptions

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ée).

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é.

set_exception_handler() n'est plus garanti de recevoir des objets Exception

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) { ... }
?>

Les constructeurs internes lèvent toujours des exceptions en cas d'échec

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'analyse lèvent une ParseError

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.

Changements de gravité des avis E_STRICT

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 provoquera pas d'erreur.

Changements de gravité des avis E_STRICT
Situation Nouveau niveau/comportement
Indexation par une ressource E_NOTICE
Méthodes statiques abstraites Avis supprimé, déclenche aucune erreur
"Redéfinir" un constructeur Avis supprimé, 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é, 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

Modifications apportées à la gestion des variables

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.

Modifications apportées à la gestion des variables, propriétés et méthodes indirectes

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é.

Ancienne et nouvelle évaluation des expressions indirectes
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};
}
?>

Modifications apportées à la gestion des list()

la liste() n'assigne plus de variable dans l'ordre inverse

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[]) = [123];
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 liste() se produisent, car il s'agit d'un détail d'implémentation qui peut changer à nouveau à l'avenir.

Les affectations de list() vides ont été supprimées

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 pas défaire chaîne de caractères

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 des tableaux a changé lorsque les éléments sont créés automatiquement pendant les affectations de référence

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)
}

Les parenthèses autour des arguments de fonction n'affectent plus le comportement

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 [
123];
}

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

Changements concernant 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 
= [012];
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.

Le comportement du parcours de 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)

Parcours d'objets non-Traversable

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.

Modifications apportées à la gestion d'entier

Littéraux octaux non valides

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.

Décalage de bits négatif

Les décalages de bits par nombres négatifs vont maintenant lancer une ArithmeticError:

<?php
var_dump
(>> -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

Décalage de bits hors plage

Les décalages de bits (dans les deux sens) au-delà de la largeur de bit d'un entier retournera toujours 0. Auparavant, le comportement de ces décalages était dépendant de l'architecture.

Changements apportés à la division par zéro

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

Modifications apportées à la gestion des chaîne de caractères

Les chaînes hexadécimales ne sont plus considérées comme numériques

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($strFILTER_VALIDATE_INTFILTER_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é.

Fonctions supprimées

call_user_method() et call_user_method_array()

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*

Toutes les fonctions ereg ont été supprimées. PCRE est une alternative recommandée.

Aliasmcrypt

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

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

Toutes les fonctions ext/mssql ont été supprimées. Pour obtenir une liste des alternatives, consultez l' introduction MSSQL.

intl aliases

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()

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.

set_socket_blocking()

L'alias obsolète set_socket_blocking() a été supprimé et remplacé par stream_set_blocking().

dl() avec PHP-FPM

dl() ne peut plus être utilisé avec PHP-FPM. Il continue à fonctionner dans les SAPIs CLI et Embed.

Fonctions GD Type1

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.

Directives INI supprimées

Fonctionnalités supprimées

Les directives INI suivantes ont été supprimées car leurs fonctionnalités associées ont également été supprimées:

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.

Autres modifications rétro-incompatibles

Les nouveaux objets ne peuvent pas être attribués par référence

Le résultat de l'instruction new ne peut plus être assigné à une variable par référence :

<?php
class {}
$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

Noms de classe, d'interface et de traits invalides

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.

ASP et script PHP Tags supprimés

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 :

Suppression des balises ASP et script
Balise d'ouverture Balise de fermeture
<% %>
<%= %>
<script language="php"> </script>

Appels d'un contexte incompatible supprimés

Précédemment déconseillé dans PHP 5.6, les appels statiques effectués à une méthode non statique avec un contexte incompatible se traduira désormais par la méthode appelée ayant une variable $this non définie et un avertissement d'obsolescence est émis.

<?php
class {
    public function 
test() { var_dump($this); }
}

// Note: Does NOT extend A
class {
    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.

Les fonctions ne peuvent pas avoir plusieurs paramètres avec le même nom

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) {
    
//
}
?>

Fonctions d'inspection des arguments signalent la valeur actuelle du paramètre

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

Les instructions Switch ne peuvent pas avoir plusieurs blocs par défaut

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 a été supprimée

$HTTP_RAW_POST_DATA n'est plus disponible. Le flux php://input doit être utilisé à la place.

Les commentaires # 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().

Extension JSON remplacée par JSOND

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.

Défaillance de la fonction interne sur le débordement

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é.

Correctifs aux valeurs de retour de gestionnaire de session personnalisé

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.

Ordre de tri des éléments égaux

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.

Instructions de coupure et de commutation mal placé

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.

Mhash n'est plus une extension

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.

declare(ticks)

La directive declare(ticks) ne fuit plus dans des unités de compilation différentes.

add a note add a note

User Contributed Notes 10 notes

up
172
me at fquff dot io
3 years ago
[Editor's note: fixed limit on user request]

As a mathematician, 3/0 == +INF IS JUST WRONG. You can't just assume 3/0 == lim_{x->0+} 3/x, which is +INF indeed, because division IS NOT A CONTINUOUS FUNCTION in x == 0.

Also, 3/0 == +INF ("positive" infinity) while -3/0 == -INF ("negative" infinity) requires the assumption that 0 is a positive number, which is just as illogical as it looks like.

The fact that a warning is emitted is good, but it should definitely equals to NaN. ±INF is just illogical (and arithmetically wrong).

Except for this "detail", looks an amazing update, can't wait to test it even further!

Cheers,
P.
up
93
mossy2100
3 years ago
Although $x/0 is technically not infinity in a purely mathematical sense, when you understand why the IEEE float includes a value for infinity, and returns infinity in this case, it makes sense that PHP would agree with this.

The reason is that programmers don't usually divide by 0 on purpose. A value of 0 as a divisor usually occurs due to underflow, i.e. a value which is too small to be represented as a float. So, for example, if you have values like:
$x = 1;
$y = 1e-15 * 1e-15;
$z = $x/$y;
Because $y will have underflowed to 0, the division operation will throw the division by zero warning, and $z will be set to INF. In a better computer, however, $y would not have the value 0 (it would be 1e-30) and $z would not have the value INF (it would be 1e30).

In other words, 0 is not only representative of an actual 0, but also a very small number which float cannot represent correctly (underflow), and INF does not only represent infinity, but also a very big number which float cannot represent correctly (overflow). We do the best we can within the limitations of floating point values, which are really just good approximations of the actual numbers being represented.

What does bother me is that division by zero is handled in two different ways depending on the operator. I would have preferred the new DivisionByZeroError exception to be thrown in all cases, for consistency and to enforce good programming practices.
up
116
tuxedobob
3 years ago
As a programmer, I don't care whether 3/0 is INF or NaN. Both answers are (probably) equally useless, and tell me that something somewhere else is screwed up.
up
9
tkondrashov at gmail dot com
8 months ago
split() was also removed in 7.0, so be sure to check your old code for it as well as the functions listed in this doc
up
4
maba at mb-systemhaus dot net
3 years ago
NOTE:
the new variable handling in PHP 7 also has side effects on the COM .NET extension. Numeric variants (in the Windows application space) now must be quoted when passed over from PHP. This is the case when the receiving application expects a variable of type variant.

Here is an example:

<?php
  $word
= new COM('Word.Application');

 
// now load a document, ...

  // the following works in PHP 5 but will throw an exception in PHP 7
 
$word->ActiveDocument->PrintOut(false, false, 0, $outfile);

 
// the following works in PHP 7 as well, please note the quotes around the '0'
 
$word->ActiveDocument->PrintOut(false, false, '0', $outfile);
?>
up
7
Frank
3 years ago
[Editor's Note: that change is listed in the "Changed functions" section.]

The substr function has also been changed in a backward incompatible way.

<?php
substr
("test",4);  # false in PHP 5,  "" in PHP 7
?>

In fact, this is the only thing we had to change in a number of places for our code base to run on PHP 7. It's definitely an improvement though, as the old behavior tended to cause bugs in border cases.
up
4
viktor dot csiky at nospam dot nospam dot eu
2 years ago
It is stated:

"foreach by-value operates on a copy of the array

When used in the default by-value mode, foreach will now operate on a copy of the array being iterated rather than the array itself. This means that changes to the array made during iteration will not affect the values that are iterated."

Please note that this is not exactly true. New foreach operates on a copy of the array, by-value or by-reference. It seems that in the latter case, the array copy is simply moved over (to) the original array before it is presumably destroyed.

As a consequence of this, you may not "dereference" an array containing values - e.g. for use with ReflectionMethod::invokeArgs() or the good ole' call_user_func().
Consider the snippet below:

<?php
function deref(Array $inputArray)
{
       
$retVal = [];
       
        foreach (
$inputArray as &$inputValue)
        {
           
$retVal[] = $inputValue;
        }

        return
$retVal;
}
?>

As of PHP 7.0, this *will no longer work*. You will get the usual suspect:

PHP Warning:  Parameter n to whatever() expected to be a reference, value given in baz.php on line x

You need to convert it to explicitly reference the original array:
<?php
function deref(Array $inputArray)
{
       
$retVal = [];
       
        foreach (
$inputArray as $inputKey => $inputValue)
        {
           
$retVal[$inputKey] = &$inputArray[$inputKey];
        }

        return
$retVal;
}
?>

PLEASE NOTE that this might have the unforeseen consequence of your code not working anymore in php versions less than 5.3 (that is, 5.2 and below).
up
-7
Ray.Paseur sometimes uses Gmail
2 years ago
In the section captioned "Changes to the handling of indirect variables, properties, and methods" there are parentheses used in the table directly beneath "PHP 7 interpretation." 

The parentheses are intended to show the evaluation order, but they are not part of the syntax, and should not be used in the variable definition or reference.  This juxtaposition confused one of my colleagues; hopefully this note will save someone else some time.

Examples of the correct curly-brace syntax is further down the page, in the section captioned "global only accepts simple variables."
up
-1
ilya dot chase at yandex dot ru
1 month ago
Take note that in preg_replace() function, flag '\e' was deleted in PHP 7.0.0. This function will return null always with this flag. Doc: https://www.php.net/manual/ru/function.preg-replace.php
To Top