Cambios que provocan incompatibilidad ascendente

Modificaciones aportadas a la gestión de errores y excepciones

Numerosos errores fatales y recuperables han sido convertidos en excepciones en PHP 7. Estas excepciones de error heredan de la clase Error, que a su vez implementa la interfaz Throwable (la nueva interfaz base de la que todas las excepciones heredan).

Esto significa que los manejadores de errores personalizados pueden no ser invocados ya que las excepciones pueden ser lanzadas en su lugar (provocando nuevos errores irrecuperables para las excepciones Error no interceptadas).

Una descripción más completa de cómo funcionan los errores en PHP 7 se encuentra en la página de errores de PHP 7. Esta guía de migración simplemente enumerará los cambios que afectan la retrocompatibilidad.

set_exception_handler() ya no está garantizado para recibir objetos Exception

El código que implementa un manejador de excepciones inscrito con set_exception_handler() usando una declaración de tipo Exception provocará un error fatal cuando un objeto Error es lanzado.

Si el manejador debe funcionar tanto con PHP 5 como con 7, debería eliminar la declaración de tipo del manejador, mientras que el código que se migra para funcionar exclusivamente en PHP 7 puede simplemente reemplazar la declaración de tipo Exception por Throwable.

<?php
// Código para PHP 5 que fallará.
function handler(Exception $e) { /* ... */ }
set_exception_handler('handler');

// Compatible con PHP 5 y 7.
function handler($e) { /* ... */ }

// Solo PHP 7.
function handler(Throwable $e) { /* ... */ }
?>

Los constructores internos lanzan excepciones en caso de fallo

Anteriormente, algunas clases internas devolvían null o un objeto inutilizable cuando el constructor fallaba. Todas las clases internas lanzarán ahora una Exception en este caso de la misma manera que las clases de usuario.

Los errores de análisis lanzan una ParseError

Los errores del analizador ahora lanzan un objeto ParseError. El manejo de errores para eval() ahora debe incluir un bloque catch que pueda manejar este error.

Cambios de severidad de los avisos E_STRICT

Todos los avisos E_STRICT han sido reclasificados a otros niveles. La constante E_STRICT se conserva, por lo que las llamadas como error_reporting(E_ALL|E_STRICT) no provocarán errores.

Cambios de severidad de los avisos E_STRICT
Situación Nuevo nivel/comportamiento
Indexación por un recurso E_NOTICE
Métodos estáticos abstractos Aviso eliminado, no dispara ningún error
"Redefinir" un constructor Aviso eliminado, no dispara ningún error
Incompatibilidad de firma durante la herencia E_WARNING
Misma propiedad (compatible) en dos rasgos usados Aviso eliminado, no dispara ningún error
Acceso a una propiedad estática de manera no estática E_NOTICE
Solo las variables deben ser asignadas por referencia E_NOTICE
Solo las variables deben ser pasadas por referencia E_NOTICE
Llamada a métodos no estáticos de manera estática E_DEPRECATED

Modificaciones en el manejo de variables

PHP 7 ahora utiliza un árbol de sintaxis abstracta al analizar los archivos fuente. Esto ha permitido numerosas mejoras en el lenguaje que anteriormente eran imposibles debido a las limitaciones en el analizador utilizado en versiones anteriores de PHP, pero ha llevado a la eliminación de algunos casos especiales por razones de consistencia, lo que ha roto la retrocompatibilidad. Estos casos se detallan en esta sección.

Modificaciones en el manejo de variables, propiedades y métodos indirectos

El acceso indirecto a variables, propiedades y métodos ahora se evaluará estrictamente en orden de izquierda a derecha, en contraste con la combinación anterior de casos especiales. La tabla a continuación muestra cómo ha cambiado el orden de evaluación.

Evaluación antigua y nueva de expresiones indirectas
Expresión Interpretación PHP 5 Interpretación 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']()

El código que utilizaba el antiguo orden de evaluación de derecha a izquierda debe ser reescrito para usar explícitamente este orden de evaluación con llaves (ver la columna del medio anterior). Esto hará que el código sea compatible con PHP 7.x y retrocompatible con PHP 5.x.

Esto también afecta a la palabra clave global. La sintaxis de llaves puede ser utilizada para emular el comportamiento anterior si es necesario:

<?php
function f() {
// Válido solo en PHP 5.
global $$foo->bar;

// Válido en PHP 5 y 7.
global ${$foo->bar};
}
?>

Modificaciones en el manejo de list()

La función list() ya no asigna variables en orden inverso

list() ahora asignará valores a las variables en el orden en que se definen, en lugar de en orden inverso. En general, esto solo afecta al caso en que list() se usa en conjunción con el operador de array [], como se ilustra a continuación:

<?php
list($a[], $a[], $a[]) = [1, 2, 3];
var_dump($a);
?>

Salida del ejemplo anterior en PHP 5:

array(3) {
  [0]=>
  int(3)
  [1]=>
  int(2)
  [2]=>
  int(1)
}

Salida del ejemplo anterior en PHP 7:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

En general, se recomienda no depender del orden en que ocurren las asignaciones de la función list(), ya que es un detalle de implementación que puede cambiar nuevamente en el futuro.

Las asignaciones vacías de list() han sido eliminadas

Las construcciones de list() ya no pueden estar vacías. Los siguientes elementos ya no están permitidos:

<?php
list() = $a;
list(,,) =
$a;
list(
$x, list(), $y) = $a;
?>
list() no puede descomponer string

list() ya no puede descomponer variables de string. Debe usarse str_split() en su lugar.

El orden de los elementos de los arrays ha cambiado cuando los elementos se crean automáticamente durante las asignaciones por referencia

El orden de los elementos en un array ha cambiado cuando estos elementos fueron creados automáticamente al referenciarlos en una asignación por referencia. Por ejemplo:

<?php
$array
= [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
?>

Salida del ejemplo anterior en PHP 5:

array(2) {
  ["b"]=>
  &int(1)
  ["a"]=>
  &int(1)
}

Salida del ejemplo anterior en PHP 7:

array(2) {
  ["a"]=>
  &int(1)
  ["b"]=>
  &int(1)
}

Los paréntesis alrededor de los argumentos de función ya no afectan el comportamiento

En PHP 5, el uso de paréntesis redundantes alrededor de un argumento de función podía silenciar las advertencias de normas estrictas cuando el argumento de función se pasaba por referencia. La advertencia ahora siempre se emite.

<?php
function getArray() {
return [
1, 2, 3];
}

function
squareArray(array &$a) {
foreach (
$a as &$v) {
$v **= 2;
}
}

// Genera una advertencia en PHP 7.
squareArray((getArray()));
?>

El resultado del ejemplo sería:

Notice: Only variables should be passed by reference in /tmp/test.php on line 13

Cambios relacionados con foreach

Se han realizado cambios menores en el comportamiento de la estructura de control foreach, principalmente en la gestión del puntero interno del array y la modificación del array mientras se recorre.

foreach ya no modifica el puntero interno del array

Antes de PHP 7, el puntero interno del array se modificaba mientras se recorría un array con foreach. Esto ya no es el caso, como se muestra en el siguiente ejemplo:

<?php
$array
= [0, 1, 2];
foreach (
$array as &$val) {
var_dump(current($array));
}
?>

Salida del ejemplo anterior en PHP 5:

int(1)
int(2)
bool(false)

Salida del ejemplo anterior en PHP 7:

int(0)
int(0)
int(0)

foreach por valor trabaja sobre una copia del array

Al utilizar el modo predeterminado (por valor), foreach ahora trabaja sobre una copia del array en lugar del array original. Esto significa que los cambios realizados en el array mientras se recorre no afectarán los valores que se están iterando.

El comportamiento de foreach por referencia ha sido mejorado

Al recorrer un array por referencia, foreach ahora identifica mejor los cambios realizados en el array durante la iteración. Por ejemplo, si se añaden valores a un array mientras se recorre, estos nuevos valores también serán iterados:

<?php
$array
= [0];
foreach (
$array as &$val) {
var_dump($val);
$array[1] = 1;
}
?>

Salida del ejemplo anterior en PHP 5:

int(0)

Salida del ejemplo anterior en PHP 7:

int(0)
int(1)

Iteración de objetos no-Traversable

La iteración de un objeto no-Traversable ahora es idéntica a la iteración de un array por referencia. Como resultado, la mejora en el comportamiento cuando se modifica un array durante su iteración también se aplica cuando se añaden o eliminan propiedades de un objeto.

Modificaciones en la gestión de int

Literales octales no válidos

Anteriormente, los literales octales que contenían números no válidos eran truncados silenciosamente (0128 se interpretaba como 012). Ahora, un literal octal no válido provocará un error de análisis.

Desplazamiento de bits negativo

Los desplazamientos de bits por números negativos ahora lanzarán una ArithmeticError:

<?php
var_dump
(1 >> -1);
?>

Salida del ejemplo anterior en PHP 5:

int(0)

Salida del ejemplo anterior 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

Desplazamiento de bits fuera de rango

Los desplazamientos de bits (en ambos sentidos) más allá del ancho de bits de un int siempre devolverán 0. Anteriormente, el comportamiento de estos desplazamientos dependía de la arquitectura.

Cambios en la división por cero

Anteriormente, cuando se utilizaba 0 como divisor en los operadores de división (/) o módulo (%), se emitía un E_WARNING y se devolvía false. Ahora, el operador de división devuelve un float como +INF, -INF o NAN, según lo especificado por IEEE 754. La advertencia E_WARNING del operador de módulo ha sido eliminada y ahora lanzará una excepción DivisionByZeroError.

<?php
var_dump
(3/0);
var_dump(0/0);
var_dump(0%0);
?>

Salida del ejemplo anterior 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)

Salida del ejemplo anterior 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

Modificaciones en el manejo de string

Las cadenas hexadecimales ya no se consideran numéricas

Las string que contienen números hexadecimales ya no se consideran numéricas. Por ejemplo:

<?php
var_dump
("0x123" == "291");
var_dump(is_numeric("0x123"));
var_dump("0xe" + "0x1");
var_dump(substr("foo", "0x1"));
?>

Salida del ejemplo anterior en PHP 5:

bool(true)
bool(true)
int(15)
string(2) "oo"

Salida del ejemplo anterior 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() puede ser utilizado para verificar si una string contiene un número hexadecimal, y también para convertir una string de este tipo en un int:

<?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{ puede causar errores

Debido a la adición de la nueva sintaxis de escape de punto de código Unicode, las string que contienen un literal \u{ seguido de una secuencia no válida provocarán un error fatal. Para evitar esto, la barra invertida principal debe ser escapada.

Funciones eliminadas

call_user_method() y call_user_method_array()

Estas funciones fueron desaprobadas en PHP 4.1.0 en favor de call_user_func() y call_user_func_array(). También puede utilizar las funciones variables y/o el operador ....

Todas las funciones ereg*

Todas las funciones ereg han sido eliminadas. PCRE es una alternativa recomendada.

Alias mcrypt

La función obsoleta mcrypt_generic_end() ha sido reemplazada por mcrypt_generic_deinit().

Además, las funciones obsoletas mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() y mcrypt_ofb() han sido reemplazadas por el uso de mcrypt_decrypt() con la constante apropiada MCRYPT_MODE_*.

Todas las funciones ext/mysql

Todas las funciones ext/mysql han sido eliminadas. Para más información sobre la elección de otra API MySQL, consulte elegir una API MySQL.

Todas las funciones ext/mssql

Todas las funciones ext/mssql han sido eliminadas.

intl alias

Los alias obsoletos datefmt_set_timezone_id() y IntlDateFormatter::setTimeZoneID() han sido eliminados y reemplazados respectivamente por datefmt_set_timezone() y IntlDateFormatter::setTimeZone().

set_magic_quotes_runtime()

set_magic_quotes_runtime(), así como su alias magic_quotes_runtime(), han sido eliminadas. Estaban obsoletas desde PHP 5.3.0 y sin efecto desde la eliminación de las comillas mágicas en PHP 5.4.0.

set_socket_blocking()

El alias obsoleto set_socket_blocking() ha sido eliminado y reemplazado por stream_set_blocking().

dl() con PHP-FPM

dl() ya no puede ser utilizado con PHP-FPM. Continúa funcionando en las SAPIs CLI y Embed.

Funciones GD Type1

El soporte para las fuentes PostScript Type1 ha sido eliminado de la extensión GD, lo que ha llevado a la eliminación de las siguientes funciones:

  • imagepsbbox()
  • imagepsencodefont()
  • imagepsextendfont()
  • imagepsfreefont()
  • imagepsloadfont()
  • imagepsslantfont()
  • imagepstext()

En su lugar, se recomienda utilizar las fuentes TrueType y sus funciones asociadas.

Directivas INI eliminadas

Funcionalidades eliminadas

Las siguientes directivas INI han sido eliminadas porque sus funcionalidades asociadas también han sido eliminadas:

  • always_populate_raw_post_data
  • asp_tags

xsl.security_prefs

La directiva xsl.security_prefs ha sido eliminada. En su lugar, el método XsltProcessor::setSecurityPrefs() debe ser llamado para controlar las preferencias de seguridad en una base por procesador.

Otras modificaciones compatibles con versiones anteriores

No se pueden asignar nuevos objetos por referencia

El resultado de la instrucción new ya no se puede asignar a una variable por referencia:

<?php
class C {}
$c =& new C;
?>

Salida del ejemplo anterior en PHP 5:

Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3

Salida del ejemplo anterior en PHP 7:

Parse error: syntax error, unexpected 'new' (T_NEW) in /tmp/test.php on line 3

Nombres de clases, interfaces y traits no válidos

Los siguientes nombres no pueden utilizarse para nombrar clases, interfaces o funciones:

Además, no deben utilizarse los siguientes nombres. Aunque no generan un error en PHP 7.0, están reservados para uso futuro y deben ser considerados obsoletos.

Etiquetas ASP y PHP eliminadas

Se ha eliminado el soporte para el uso de etiquetas ASP y script para delimitar código PHP. Las etiquetas afectadas son:

Eliminación de etiquetas ASP y script
Etiqueta de apertura Etiqueta de cierre
<% %>
<%= %>
<script language="php"> </script>

Llamadas desde un contexto incompatible eliminadas

Anteriormente no recomendado en PHP 5.6, Las llamadas estáticas a un método no estático con un contexto incompatible ahora resultarán en que el método llamado tendrá un indefinido $this y se emitirá una advertencia de obsolescencia.

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

// Nota: NO extiende A
class B {
public function
callNonStaticMethodOfA() { A::test(); }
}

(new
B)->callNonStaticMethodOfA();
?>

Salida del ejemplo anterior 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) {
}

Salida del ejemplo anterior 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 es ahora un operador asociativo derecho

La construcción yield ya no requiere paréntesis y ha sido sustituida por un operador asociativo derecho con prioridad entre print y =>. Esto puede provocar un cambio en el comportamiento:

<?php
echo yield -1;
// Antes se interpretaba como
echo (yield) - 1;
// Y ahora se interpreta como
echo yield (-1);

yield
$foo or die;
// Antes se interpretaba como
yield ($foo or die);
// Y ahora se interpreta como
(yield $foo) or die;
?>

Los paréntesis pueden utilizarse para eliminar la ambigüedad en estos casos.

Las funciones no pueden tener varios parámetros con el mismo nombre

Ya no es posible definir dos o más parámetros de función con el mismo nombre. Por ejemplo, la siguiente función desencadenará un E_COMPILE_ERROR:

<?php
function foo($a, $b, $unused, $unused) {
//
}
?>

Las funciones de inspección de argumentos informan del valor actual del parámetro

func_get_arg(), func_get_args(), debug_backtrace() y las trazas de excepciones ya no devuelven el valor original que se pasó a un parámetro, sino que proporcionarán el valor actual (que podría haber sido modificado).

<?php
function foo($x) {
$x++;
var_dump(func_get_arg(0));
}
foo(1);?>

Salida del ejemplo anterior en PHP 5:

1

Salida del ejemplo anterior en PHP 7:

2

Las instrucciones de conmutación no pueden tener varios bloques por defecto

Ya no es posible definir dos o más bloques por defecto en una instrucción de conmutación. Por ejemplo, la siguiente instrucción switch desencadenará una E_COMPILE_ERROR:

<?php
switch (1) {
default:
break;
default:
break;
}
?>

$HTTP_RAW_POST_DATA ha sido eliminado

$HTTP_RAW_POST_DATA ya no está disponible. El flujo php://input debe ser utilizado en su lugar.

Los comentarios # en los archivos INI han sido eliminados

Se ha eliminado el soporte para los comentarios con el prefijo # en los archivos INI. ; (punto y coma) debe ser utilizado en su lugar. Este cambio se aplica a los archivos php.ini, así como a los archivos gestionados por parse_ini_file() y parse_ini_string().

Extensión JSON reemplazada por JSOND

La extensión JSON ha sido reemplazada por JSOND, provocando tres incompatibilidades BC menores. Primero, un número no debe terminar con una coma decimal (es decir, 34. debe ser cambiado a 34.0 o a 34). Segundo, al usar la notación científica, el exponente e no debe seguir inmediatamente a un punto decimal (es decir, 3.e3 debe ser cambiado a 3.0e3 o a 3e3). Finalmente, una cadena vacía ya no se considera como JSON válido.

Fallo de la función interna en caso de desbordamiento

Anteriormente, las funciones internas debían truncar silenciosamente los números producidos a partir de restricciones de tipo float a entero cuando el número era demasiado grande para representar un entero. Ahora, se emitirá un E_WARNING y se devolverá null.

Correcciones a los valores de retorno del manejador de sesión personalizado

Todas las funciones de predicado implementadas por manejadores de sesión personalizados que devuelvan false o -1 serán errores fatales. Si se devuelve un valor de estas funciones distinto de un booleano, -1 o 0, fallará y se emitirá un E_WARNING.

Orden de clasificación de elementos iguales

El algoritmo de clasificación interno ha sido mejorado, lo que puede resultar en un orden de clasificación diferente de los elementos que se comparaban como iguales anteriormente.

Nota:

No dependa del orden de los elementos que se comparan como iguales; podría cambiar en cualquier momento.

Instrucciones de interrupción y continuación mal ubicadas

Las instrucciones break y continue fuera de un bucle o una estructura de control switch ahora se detectan en el momento de la compilación en lugar de la ejecución como antes, y desencadenan un E_COMPILE_ERROR.

Constante prohibida como argumento de break y continue

Las instrucciones break y continue ya no permiten que su argumento sea una constante, y desencadenan un E_COMPILE_ERROR.

Mhash ya no es una extensión

La extensión mhash ha sido completamente integrada en la extensión Hash. Por lo tanto, ya no es posible detectar el soporte mhash con extension_loaded(); utilizar function_exists() en su lugar. Además, mhash ya no se reporta por get_loaded_extensions() y las funcionalidades relacionadas.

declare(ticks)

La directiva declare(ticks) ya no se filtra en diferentes unidades de compilación.

add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top