Referencia de PHP 7.2
Referencia de PHP 7.1
PHP 7 se lanzó el 3 de diciembre de 2015. Viene con una serie de características nuevas, cambios y fallas de compatibilidad con versiones anteriores que se describen a continuación.
Actuación
Características
Operador de comparación combinado
Operador de fusión nula
Declaraciones de tipo escalar
Declaraciones de tipo de devolución
Clases anónimas
Sintaxis de escape de punto de código Unicode
Método de call()
unserialize()
Clase IntlChar
Esperanzas de heredar
Declaraciones use
grupal
Expresiones de retorno del generador
Delegación Generadora
División entera con intdiv()
Opciones session_start()
Función preg_replace_callback_array()
Funciones CSPRNG
Soporte para constantes de matriz en define()
Adiciones de reflexión
Cambios
Aflojar las restricciones de palabras reservadas
Sintaxis de variable uniforme
Excepciones en el motor
Interfaz arrojable
Semántica de enteros
Extensión JSON reemplazada por JSOND
Fallo de ZPP en desbordamiento
Correcciones al comportamiento de foreach()
Cambios en el comportamiento de list()
Cambios en la división por semántica cero
Correcciones a los valores de retorno del controlador de sesión personalizado
Desuso de los constructores de estilo PHP 4
Eliminación de la advertencia date.timezone
Eliminación de etiquetas PHP alternativas
Eliminación de múltiples bloques predeterminados en declaraciones de cambio
Eliminación de la redefinición de parámetros con nombres duplicados
Eliminación de API de servidor inactivo
Eliminación del soporte hexadecimal en cadenas numéricas
Eliminación de funcionalidad obsoleta
Reclasificación y eliminación de avisos E_STRICT
Desuso de la opción Salt para password_hash()
Error en literales octales no válidos
substr()
Cambio de valor de retorno
Preguntas frecuentes
¿Qué pasó con PHP 6?
Sin duda, la mejor parte de PHP 7 es el increíble aumento de rendimiento que proporciona a las aplicaciones. Este es el resultado de refactorizar Zend Engine para utilizar estructuras de datos más compactas y menos asignaciones/desasignaciones de montón.
Las ganancias de rendimiento en aplicaciones del mundo real variarán, aunque muchas aplicaciones parecen recibir un aumento de rendimiento de ~100%, ¡con un menor consumo de memoria también!
La base de código refactorizada también ofrece más oportunidades para futuras optimizaciones (como la compilación JIT). Por lo tanto, parece que las futuras versiones de PHP también seguirán viendo mejoras de rendimiento.
Comparaciones de gráficos de rendimiento de PHP 7:
Impulsando la Web con PHP 7
Puntos de referencia de la charla de Rasmus en Sydney
El operador de comparación combinado (u operador de nave espacial) es una notación abreviada para realizar comparaciones de tres vías a partir de dos operandos. Tiene un valor de retorno entero que puede ser:
un número entero positivo (si el operando de la izquierda es mayor que el operando de la derecha)
0 (si ambos operandos son iguales)
un entero negativo (si el operando de la derecha es mayor que el operando de la izquierda)
El operador tiene la misma precedencia que los operadores de igualdad ( ==
, !=
, ===
, !==
) y tiene exactamente el mismo comportamiento que los otros operadores de comparación flexibles ( <
, >=
, etc.). También es no asociativo como ellos, por lo que no se permite el encadenamiento de operandos (como 1 <=> 2 <=> 3
).
// compara cadenas lexicallyvar_dump('PHP' <=> 'Node'); // int(1)// compara números por sizevar_dump(123 <=> 456); // int(-1)// compara los elementos de matriz correspondientes entre sí var_dump(['a', 'b'] <=> ['a', 'b']); //int(0)
Los objetos no son comparables, por lo que usarlos como operandos con este operador dará como resultado un comportamiento indefinido.
RFC: Operador de comparación combinado
El operador de fusión nula (u operador ternario isset) es una notación abreviada para realizar comprobaciones isset()
en el operador ternario. Esto es algo común en las aplicaciones, por lo que se ha introducido una nueva sintaxis para este propósito exacto.
// Código anterior a PHP 7$ruta = isset($_GET['ruta'])? $_GET['ruta'] : 'índice';// Código PHP 7+$ruta = $_GET['ruta'] ?? 'índice';
RFC: operador de fusión nula
Las declaraciones de tipo escalar vienen en dos tipos: coercitivas (predeterminadas) y estrictas . Ahora se pueden aplicar los siguientes tipos de parámetros (ya sea de forma coercitiva o estricta): cadenas ( string
), enteros ( int
), números de punto flotante ( float
) y booleanos ( bool
). Aumentan los otros tipos introducidos en las versiones PHP 5.x: nombres de clases, interfaces, array
y callable
.
// Función de modo coercitivo sumaDeInts(int ...$ints) { return array_sum($ints); }var_dump(sumOfInts(2, '3', 4.1)); //int(9)
Para habilitar el modo estricto, se debe colocar una única directiva declare()
en la parte superior del archivo. Esto significa que el rigor de la escritura de escalares se configura por archivo. Esta directiva no solo afecta las declaraciones de tipo de parámetros, sino también el tipo de retorno de una función (consulte Declaraciones de tipo de retorno), funciones PHP integradas y funciones de extensiones cargadas.
Si la verificación de tipo falla, se genera una excepción TypeError
(consulte Excepciones en el motor). La única indulgencia presente en la tipificación estricta es la conversión automática de números enteros a flotantes (pero no al revés) cuando se proporciona un número entero en un contexto flotante.
declarar(tipos_estrictos=1);función multiplicar(flotante $x, flotante $y) { devolver $x * $y; }función agregar(int $x, int $y) { devolver $x + $y; }var_dump(multiplicar(2, 3.5)); // float(7)var_dump(add('2', 3)); // Error grave: TypeError no detectado: el argumento 1 pasado a add() debe ser del tipo entero, cadena proporcionada...
Tenga en cuenta que solo se aplica el contexto de invocación cuando se realiza la verificación de tipo. Esto significa que la tipificación estricta se aplica solo a las llamadas a funciones/métodos, y no a las definiciones de funciones/métodos. En el ejemplo anterior, las dos funciones podrían haberse declarado en un archivo estricto o coercitivo, pero siempre que se llamen en un archivo estricto, se aplicarán las reglas de escritura estrictas.
BC se rompe
Las clases con nombres int
, string
, float
y bool
ahora están prohibidas.
RFC: Declaraciones de tipo escalar
Las declaraciones de tipo de retorno permiten especificar el tipo de retorno de una función, método o cierre. Se admiten los siguientes tipos de retorno: string
, int
, float
, bool
, array
, callable
, self
(solo métodos), parent
(solo métodos), Closure
, el nombre de una clase y el nombre de una interfaz.
función suma_arrays(matriz...$matriz): matriz{ return array_map(función(matriz $matriz): int { return matriz_sum($matriz); }, $matrices); }print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));/* OutputArray( [0] => 6 [1] => 15 [2] => 24)*/
Con respecto a los subtipos, se ha elegido la invariancia para los tipos de devolución. Esto simplemente significa que cuando un método se anula en una clase subtipada o se implementa según lo definido en un contrato, su tipo de retorno debe coincidir exactamente con el método que está (re)implementando.
clase A {}clase B extiende A {}clase C {prueba de función pública(): A { devolver nueva A; } }clase D extiende C { // método anulado C::test() : Una función pública test() : B // Error fatal debido a una discrepancia en la varianza { devolver nueva B; } }
El método principal D::test() : B
provoca un E_COMPILE_ERROR
porque no se permite la covarianza. Para que esto funcione, el método D::test()
debe tener un tipo de retorno de A
.
clase A {}interfaz AlgunaInterfaz { prueba de función pública() : A; }la clase B implementa SomeInterface { prueba de función pública() : A // ¡todo bien! {retorno nulo; // Error fatal: TypeError no detectado: el valor de retorno de B::test() debe ser una instancia de A, se devuelve nulo... } }
Esta vez, el método implementado provoca que se genere una excepción TypeError
(consulte Excepciones en el motor) cuando se ejecuta. Esto se debe a que null
no es un tipo de retorno válido; solo se puede devolver una instancia de la clase A
RFC: Declaraciones de tipo de devolución
Las clases anónimas son útiles cuando es necesario crear objetos simples y únicos.
// Registrador de clase de código anterior a PHP 7 { registro de función pública ($msg) { echo $mensaje; } }$util->setLogger(new Logger());// Código PHP 7+$util->setLogger(nueva clase { registro de función pública($msg) { echo $mensaje; } });
Pueden pasar argumentos a sus constructores, extender otras clases, implementar interfaces y usar rasgos tal como lo puede hacer una clase normal:
clase SomeClass {}interfaz SomeInterface {}rasgo SomeTrait {}var_dump(nueva clase(10) extiende SomeClass implementa SomeInterface { privado $num; función pública __construct($num) { $this->núm = $núm; } utilizar algún rasgo; });/** Salida:object(class@anonymous)#1 (1) { ["Código de línea de comando0x104c5b612":"class@anonymous":private]=> int(10)}*/
Anidar una clase anónima dentro de otra clase no le da acceso a ningún método o propiedad privada o protegida de esa clase externa. Para utilizar las propiedades o métodos protegidos de la clase externa, la clase anónima puede extender la clase externa. Para utilizar las propiedades privadas o protegidas de la clase externa en la clase anónima, se deben pasar a través de su constructor:
<?phpclass exterior { privado $prop = 1; protegido $prop2 = 2; función protegida func1() {regresar 3; } función pública func2() { return new class($this->prop) extiende Outer { privado $prop3; función pública __construct($prop) { $esto->prop3 = $prop; } función pública func3() { return $this->prop2 + $this->prop3 + $this->func1(); } }; } }echo (nuevo exterior)->func2()->func3(); // 6
RFC: Clases anónimas
Esto permite que un punto de código Unicode codificado en UTF-8 se genere en una cadena entre comillas dobles o en un documento heredoc. Se acepta cualquier punto de código válido, siendo opcional el 0
inicial.
eco "u{aa}"; // ªecho "u{0000aa}"; // ª (igual que antes pero con ceros iniciales opcionales)echo "u{9999}"; // 香
RFC: Sintaxis de escape de punto de código Unicode
El nuevo método call()
para cierres se utiliza como una forma abreviada de invocar un cierre mientras se le vincula el alcance de un objeto. Esto crea un código más eficiente y compacto al eliminar la necesidad de crear un cierre intermedio antes de invocarlo.
clase A {privado $x = 1;}// Código anterior a PHP 7$getXCB = function() {return $this->x;};$getX = $getXCB->bindTo(new A, 'A'); // cierre intermedioecho $getX(); // 1// Código PHP 7+$getX = function() {return $this->x;};echo $getX->call(new A); // 1
RFC: Cierre::llamada
unserialize()
Esta característica busca brindar una mejor seguridad al deserializar objetos en datos que no son de confianza. Evita posibles inyecciones de código al permitir que el desarrollador incluya en la lista blanca clases que se pueden deserializar.
// convierte todos los objetos en __PHP_Incomplete_Class objeto$data = unserialize($foo, ["allowed_classes" => false]);// convierte todos los objetos en __PHP_Incomplete_Class objeto excepto aquellos de MyClass y MyClass2$data = unserialize($foo, [" Allow_classes" => ["MyClass", "MyClass2"]]);// comportamiento predeterminado (igual que omitir el segundo argumento) que acepta todas las clases$data = unserialize($foo, ["allowed_classes" => true]);
RFC: Deserializar filtrado()
IntlChar
La nueva clase IntlChar
busca exponer funcionalidades adicionales de la UCI. La clase en sí define una serie de métodos estáticos y constantes que se pueden utilizar para manipular caracteres Unicode.
printf('%x', IntlChar::CODEPOINT_MAX); // 10ffffecho IntlChar::charName('@'); // COMERCIAL ATvar_dump(IntlChar::ispunct('!')); //bool(verdadero)
Para poder utilizar esta clase, se debe instalar la extensión Intl
.
BC se rompe
Las clases en el espacio de nombres global no deben llamarse IntlChar
.
RFC: clase IntlChar
Las expectativas son una mejora compatible con versiones anteriores de la función assert()
anterior. Permiten afirmaciones de costo cero en el código de producción y brindan la capacidad de generar excepciones personalizadas en caso de error.
El prototipo de la función assert()
es el siguiente:
void assert (mixed $expression [, mixed $message]);
Al igual que con la API anterior, si $expression
es una cadena, se evaluará. Si el primer argumento es falso, entonces la afirmación falla. El segundo argumento puede ser una cadena simple (que provoca que se active un AssertionError) o un objeto de excepción personalizado que contiene un mensaje de error.
ini_set('assert.exception', 1);class CustomError extiende AssertionError {}assert(false, new CustomError('Algún mensaje de error'));
Con esta característica vienen dos configuraciones de PHP.ini (junto con sus valores predeterminados):
zend.afirmaciones = 1
afirmar.excepción = 0
zend.assertions tiene tres valores:
1 = generar y ejecutar código (modo de desarrollo)
0 = generar código y saltar sobre él en tiempo de ejecución
-1 = no generar ningún código (coste cero, modo de producción)
afirmar.excepción significa que se lanza una excepción cuando falla una aserción. Esto está desactivado de forma predeterminada para seguir siendo compatible con la antigua función assert()
.
RFC: Expectativas
use
grupal Esto brinda la posibilidad de agrupar múltiples declaraciones use
según el espacio de nombres principal. Esto busca eliminar la verbosidad del código al importar múltiples clases, funciones o constantes que pertenecen al mismo espacio de nombres.
// Código anterior a PHP 7use somenamespaceClassA;use somenamespaceClassB;use somenamespaceClassC como C;use la función somenamespacefn_a;use la función somenamespacefn_b;use la función somenamespace fn_c;use const somenamespaceConstA;use const somenamespaceConstB;use const somenamespaceConstC;// PHP 7+ codeuse somenamespace{ClassA, ClassB, ClassC como C};use la función somenamespace{fn_a, fn_b, fn_c};use const somenamespace{ConstA, ConstB, ConstC};
RFC: Declaraciones de uso grupal
Esta característica se basa en la funcionalidad del generador introducida en PHP 5.5. Permite utilizar una declaración return
dentro de un generador para permitir que se devuelva una expresión final (no se permite la devolución por referencia). Este valor se puede recuperar usando el nuevo método Generator::getReturn()
, que solo se puede usar una vez que el generador haya terminado de generar valores.
// La sintaxis IIFE ahora es posible; consulte la subsección Sintaxis de variable uniforme en la sección Cambios$gen = (function() { rendimiento 1; rendimiento 2; retorno 3; })();foreach ($gen como $val) { echo $val, PHP_EOL; }echo $gen->getReturn(), PHP_EOL;// salida:// 1// 2// 3
Ser capaz de devolver explícitamente un valor final de un generador es una habilidad útil. Esto se debe a que permite que un generador devuelva un valor final (quizás a partir de alguna forma de cálculo de rutina) que puede ser manejado específicamente por el código del cliente que ejecuta el generador. Esto es mucho más simple que forzar al código del cliente a verificar primero si se ha obtenido el valor final y luego, si es así, a manejar ese valor específicamente.
RFC: expresiones de retorno del generador
La delegación del generador se basa en la capacidad de poder devolver expresiones de los generadores. Para ello, utiliza una nueva sintaxis de yield from <expr>
, donde puede haber cualquier objeto o matriz Traversable
. Esto avanzará hasta que ya no sea válido y luego la ejecución continuará en el generador de llamadas. Esta característica permite dividir las declaraciones yield
en operaciones más pequeñas, promoviendo así un código más limpio y con mayor reutilización.
función gen() { rendimiento 1; rendimiento 2; devolver rendimiento de gen2(); }función gen2() { rendimiento 3; devolver 4; }$gen = gen();foreach ($gen como $val) { eco $val, PHP_EOL; }echo $gen->getReturn();// salida// 1// 2// 3// 4
RFC: Delegación Generadora
intdiv()
La función intdiv()
se ha introducido para manejar la división donde se va a devolver un número entero.
var_dump(intdiv(10, 3)); //int(3)
BC se rompe
Las funciones en el espacio de nombres global no deben llamarse intdiv
.
RFC: intdiv()
session_start()
Esta característica brinda la posibilidad de pasar una serie de opciones a la función session_start()
. Esto se utiliza para configurar las opciones de php.ini basadas en sesiones:
session_start(['cache_limiter' => 'privado']); // establece la opción session.cache_limiter en privada
Esta característica también introduce una nueva configuración de php.ini ( session.lazy_write
) que, de forma predeterminada, está configurada en verdadero y significa que los datos de la sesión solo se reescriben si cambian.
RFC: Introducir las opciones session_start()
preg_replace_callback_array()
Esta nueva función permite escribir código de forma más limpia cuando se utiliza la función preg_replace_callback()
. Antes de PHP 7, las devoluciones de llamada que debían ejecutarse mediante expresión regular requerían que la función de devolución de llamada (segundo parámetro de preg_replace_callback()
) estuviera contaminada con muchas ramificaciones (un método hacky en el mejor de los casos).
Ahora, las devoluciones de llamada se pueden registrar para cada expresión regular usando una matriz asociativa, donde la clave es una expresión regular y el valor es una devolución de llamada.
Firma de función:
string preg_replace_callback_array(array $regexesAndCallbacks, string $input);
$tokenStream = []; // [nombre del token, lexema] pares$entrada = <<<'end'$a = 3; // inicialización de variableend;// Codepreg_replace_callback anterior a PHP 7( [ '~$[a-z_][azd_]*~i', '~=~', '~[d]+~', '~;~', '~//.*~' ], función ($match) use (&$tokenStream) { if (strpos($match[0], '$') === 0) { $tokenStream[] = ['T_VARIABLE', $match[0]] ; } elseif (strpos($match[0], '=') === 0) { $tokenStream[] = ['T_ASSIGN', $match[0]]; } elseif (ctype_digit($match[0])) { $tokenStream[] = ['T_NUM', $match[0]]; } elseif (strpos($match[0], ';') === 0) { $tokenStream[] = ['T_TERMINATE_STMT', $match[0]]; } elseif (strpos($match[0], '//') === 0) { $tokenStream[] = ['T_COMMENT', $match[0]]; } }, $entrada);// PHP 7+ codepreg_replace_callback_array( [ '~$[a-z_][azd_]*~i' => función ($match) use (&$tokenStream) { $tokenStream[] = ['T_VARIABLE', $match[0]]; }, '~=~' => función ($match) use (&$tokenStream) { $tokenStream[] = ['T_ASSIGN', $match[0]]; }, '~[d]+~' => función ($match) use (&$tokenStream) { $tokenStream[] = ['T_NUM', $match[0]]; }, '~;~' => función ($match) use (&$tokenStream) { $tokenStream[] = ['T_TERMINATE_STMT', $match[0]]; }, '~//.*~' => función ($match) use (&$tokenStream) { $tokenStream[] = ['T_COMMENT', $match[0]]; } ], $entrada);
BC se rompe
Las funciones en el espacio de nombres global no deben llamarse preg_replace_callback_array
.
RFC: Agregar función preg_replace_callback_array
Esta característica introduce dos nuevas funciones para generar cadenas y números enteros criptográficamente seguros. Exponen API simples y son independientes de la plataforma.
Firmas de funciones:
string random_bytes(int length); int random_int(int min, int max);
Ambas funciones emitirán una excepción Error
si no se puede encontrar una fuente de aleatoriedad suficiente.
BC se rompe
Las funciones en el espacio de nombres global no deben llamarse random_int
o random_bytes
.
RFC: CSPRNG fácil de usar
define()
La capacidad de definir constantes de matriz se introdujo en PHP 5.6 utilizando la palabra clave const
. Esta capacidad ahora también se ha aplicado a la función define()
:
define('ALLOWED_IMAGE_EXTENSIONS', ['jpg', 'jpeg', 'gif', 'png']);
RFC: no hay RFC disponible
Se han introducido dos nuevas clases de reflexión en PHP 7. La primera es ReflectionGenerator
, que se utiliza para la introspección en generadores:
clase Generador de Reflexión { public __construct(Generador $gen) matriz pública getTrace($opciones = DEBUG_BACKTRACE_PROVIDE_OBJECT) público int getExecutingLine (nulo) cadena pública getExecutingFile(void) función de reflexión pública función get abstracta (vacío) Objeto público getThis (vacío) Generador público getExecutingGenerator (vacío) }
El segundo es ReflectionType
para admitir mejor las características de declaración de tipo escalar y de retorno:
clase Tipo de reflexión { public bool permite Null (void) public bool isBuiltin (void) cadena pública __toString (void) }
Además, se han introducido dos nuevos métodos en ReflectionParameter
:
clase Parámetro de reflexión { // ... public bool hasType(void) public ReflectionType getType(void) }
Además de dos nuevos métodos en ReflectionFunctionAbstract
:
clase ReflexiónFunciónResumen { // ... public bool hasReturnType(void) public ReflectionType getReturnType(void) }
BC se rompe
Las clases en el espacio de nombres global no deben llamarse ReflectionGenerator
o ReflectionType
.
RFC: no hay RFC disponible
Ahora se permiten palabras reservadas globalmente como nombres de propiedades, constantes y métodos dentro de clases, interfaces y rasgos. Esto reduce la superficie de interrupciones de BC cuando se introducen nuevas palabras clave y evita restricciones de nombres en las API.
Esto es particularmente útil al crear DSL internos con interfaces fluidas:
// 'nuevo', 'privado' y 'para' antes eran inutilizablesProject::new('Nombre del proyecto')->private()->for('propósito aquí')->with('nombre de usuario aquí');
La única limitación es que la palabra clave class
todavía no se puede utilizar como nombre constante; de lo contrario, entraría en conflicto con la sintaxis de resolución del nombre de clase ( ClassName::class
).
RFC: Lexer sensible al contexto
Este cambio aporta una ortogonalidad mucho mayor a los operadores de variables en PHP. Permite una serie de nuevas combinaciones de operadores que antes no estaban permitidas y, por lo tanto, introduce nuevas formas de lograr operaciones antiguas en código más conciso.
// anidamiento ::$foo::$bar::$baz // accede a la propiedad $baz de la propiedad $foo::$bar// anidamiento ()foo()() // invoca el retorno de foo() // operadores en expresiones encerradas en ()(función () {})() // sintaxis IIFE de JS
La capacidad de combinar arbitrariamente operadores de variables surgió de revertir la semántica de evaluación de las referencias a variables indirectas, propiedades y métodos. El nuevo comportamiento es más intuitivo y siempre sigue un orden de evaluación de izquierda a derecha:
// antiguo significado // nuevo significado$$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']()
BC se rompe
El código que dependía del orden de evaluación anterior debe reescribirse para usar explícitamente ese orden de evaluación entre llaves (consulte la columna central de lo anterior). Esto hará que el código sea compatible con PHP 7.x y compatible con PHP 5.x.
RFC: sintaxis de variable uniforme
Las excepciones en el motor convierten muchos errores fatales y recuperables en excepciones. Esto permite una degradación elegante de las aplicaciones mediante procedimientos personalizados de manejo de errores. También significa que ahora se ejecutarán funciones impulsadas por la limpieza, como la cláusula finally
y los destructores de objetos. Además, al utilizar excepciones para errores de aplicación, se generarán seguimientos de pila para obtener información de depuración adicional.
función suma(flotante...$números): flotante{ return array_sum($números); }intenta { $total = suma(3, 4, nulo); } catch (TypeError $typeErr) { // maneja el error de tipo aquí}
La nueva jerarquía de excepciones es la siguiente:
interface Throwable |- Exception implements Throwable |- ... |- Error implements Throwable |- TypeError extends Error |- ParseError extends Error |- AssertionError extends Error |- ArithmeticError extends Error |- DivisionByZeroError extends ArithmeticError
Consulte la subsección Interfaz arrojable en la sección Cambios para obtener más información sobre esta nueva jerarquía de excepciones.
BC se rompe
Los controladores de errores personalizados utilizados para manejar (y generalmente ignorar) errores fatales recuperables ya no funcionarán ya que ahora se generarán excepciones.
Los errores de análisis que ocurren en el código de edición de eval()
ahora se convertirán en excepciones, lo que requerirá que se incluyan en un bloque try...catch
.
RFC: Excepciones en el Motor
Este cambio afecta la jerarquía de excepciones de PHP debido a la introducción de excepciones en el motor. En lugar de colocar errores fatales y recuperables bajo la jerarquía de clases de Exception
preexistente, se decidió implementar una nueva jerarquía de excepciones para evitar que el código PHP 5.x detecte estas nuevas excepciones con catch-all ( catch (Exception $e)
) cláusulas.
La nueva jerarquía de excepciones es la siguiente:
interface Throwable |- Exception implements Throwable |- ... |- Error implements Throwable |- TypeError extends Error |- ParseError extends Error |- AssertionError extends Error |- ArithmeticError extends Error |- DivisionByZeroError extends ArithmeticError
La interfaz Throwable
se implementa mediante jerarquías de clases base de Exception
y Error
y define el siguiente contrato:
interface Throwable { final public string getMessage ( void ) final public mixed getCode ( void ) final public string getFile ( void ) final public int getLine ( void ) final public array getTrace ( void ) final public string getTraceAsString ( void ) public string __toString ( void ) }
Throwable
no se puede implementar mediante clases definidas por el usuario; en cambio, una clase de excepción personalizada debe extender una de las clases de excepciones preexistentes en PHP.
RFC: Interfaz arrojable
La semántica de algunos comportamientos basados en números enteros ha cambiado en un esfuerzo por hacerlos más intuitivos e independientes de la plataforma. Aquí hay una lista de esos cambios:
Convertir NAN
e INF
a un número entero siempre dará como resultado 0
El cambio bit a bit por un número negativo de bits ahora no está permitido (provoca un retorno bool (falso) y emite un E_WARNING)
Los desplazamientos bit a izquierda en una cantidad de bits más allá del ancho de bits de un número entero siempre darán como resultado 0
Los desplazamientos bit a bit hacia la derecha en una cantidad de bits más allá del ancho de bits de un número entero siempre darán como resultado 0 o -1 (dependiente del signo)
BC se rompe
Cualquier dependencia de la antigua semántica para lo anterior ya no funcionará.
RFC: Semántica de enteros
La licencia de la antigua extensión JSON se consideraba no gratuita, lo que causaba problemas en muchas distribuciones basadas en Linux. Desde entonces, la extensión ha sido reemplazada por JSOND y viene con algunas mejoras de rendimiento y fallas en la compatibilidad con versiones anteriores.
BC se rompe
Un número no debe terminar en un punto decimal (es decir, 34.
debe cambiarse a 34.0
o solo 34
).
El exponente e
no debe seguir inmediatamente al punto decimal (es decir, 3.e3
debe cambiarse a 3.0e3
o simplemente 3e3
).
RFC: Reemplace la extensión json actual con jsond
La coerción entre flotantes y enteros puede ocurrir cuando se pasa un flotante a una función interna que espera un número entero. Si el valor flotante es demasiado grande para representarlo como un número entero, entonces el valor se truncará silenciosamente (lo que puede resultar en una pérdida de magnitud y signo). Esto puede introducir errores difíciles de encontrar. Por lo tanto, este cambio busca notificar al desarrollador cuando se produjo una conversión implícita de un flotante a un entero y falló al devolver null
y emitir un E_WARNING.
BC se rompe
El código que alguna vez funcionó silenciosamente ahora emitirá un E_WARNING y puede fallar si el resultado de la invocación de la función se pasa directamente a otra función (ya que ahora se pasará null
).
RFC: Fallo de ZPP en desbordamiento
foreach()
El bucle foreach()
de PHP tenía una serie de casos extremos extraños. Todos estos estaban impulsados por la implementación y causaban muchos comportamientos indefinidos e inconsistentes al iterar entre copias y referencias de una matriz, al usar manipuladores de iteradores como current()
y reset()
, al modificar la matriz que se está iterando actualmente, etc.
Este cambio elimina el comportamiento indefinido de estos casos extremos y hace que la semántica sea más predecible e intuitiva.
foreach()
por valor en matrices
$matriz = [1,2,3];$matriz2 = &$matriz;foreach($matriz como $val) { sin configurar($matriz[1]); // modificar la matriz que se itera sobre echo "{$val} - ", current($array), PHP_EOL; }// Resultado anterior a PHP 71 - 33 -// Resultado PHP 7+1 - 12 - 13 - 1
Cuando se utiliza la semántica por valor, la matriz sobre la que se itera ahora no se modifica in situ. current()
ahora también tiene un comportamiento definido, donde siempre comenzará al inicio de la matriz.
foreach()
por referencia en matrices y objetos y por valor en objetos
$matriz = [1,2,3];foreach($matriz como &$val) { echo "{$val} - ", actual($matriz), PHP_EOL; }// Resultado anterior a PHP 71 - 22 - 33 -// Resultado PHP 7+1 - 12 - 13 - 1
La función current()
ya no se ve afectada por la iteración de foreach()
en la matriz. Además, foreach()
anidados que usan semántica por referencia ahora funcionan de forma independiente entre sí:
$matriz = [1,2,3];foreach($matriz como &$val) { echo $val, PHP_EOL; foreach ($matriz como &$val2) { sin configurar($matriz[1]); eco $val, PHP_EOL; } }// Resultado anterior a PHP 7111// Resultado de PHP 7+111333
BC se rompe
Cualquier dependencia de la semántica antigua (estrafalaria e indocumentada) ya no funcionará.
RFC: corrige el comportamiento "foreach"
list()
Se documentó que la función list()
no admite cadenas; sin embargo, en algunos casos se podrían haber utilizado cadenas:
// desreferenciación de matriz$cadena[0] = 'ab';lista($a, $b) = $cadena[0];echo $a; // eco $b; // b// desreferenciación de objetos$obj = new StdClass();$obj->prop = 'ab';list($a, $b) = $obj->prop;echo $a; // eco $b; // b// función retornofunción func() {retorno 'ab'; }lista($a, $b) = func();var_dump($a, $b);echo $a; // eco $b; // b
Esto ahora se ha cambiado, haciendo que el uso de cadenas con list()
esté prohibido en todos los casos.
Además, las list()
ahora son un error fatal y el orden de asignación de variables se ha cambiado de izquierda a derecha:
$a = [1, 2];list($a, $b) = $a;// ANTIGUO: $a = 1, $b = 2// NUEVO: $a = 1, $b = null + "Indefinido index 1"$b = [1, 2];list($a, $b) = $b;// ANTIGUO: $a = null + "Índice no definido 0", $b = 2// NUEVO: $a = 1, $b = 2
BC se rompe
Ya no es posible hacer que list()
sea igual a cualquier valor de cadena no directo. null
ahora será el valor de las variables $a
y $b
en los ejemplos anteriores
Invocar list()
sin ninguna variable provocará un error fatal
La dependencia del antiguo orden de asignación de derecha a izquierda ya no funcionará
RFC: Arreglar la inconsistencia del comportamiento de la lista ()
RFC: árbol de sintaxis abstracta
Antes de PHP 7, cuando un divisor era 0 para los operadores de división (/) o módulo (%), se emitía un E_WARNING y se devolvía false
. No tenía sentido que una operación aritmética devolviera un valor booleano en algunos casos, por lo que el comportamiento se rectificó en PHP 7.
El nuevo comportamiento hace que el operador de división devuelva un valor flotante como +INF, -INF o NAN. El operador de módulo E_WARNING se eliminó y (junto con la nueva función intdiv()
) generará una excepción DivisionByZeroError
. Además, la función intdiv()
también puede generar un ArithmeticError
cuando se proporcionan argumentos enteros válidos que causan un resultado incorrecto (debido a un desbordamiento de enteros).
var_dump(3/0); // flotador(INF) + E_WARNINGvar_dump(0/0); // flotador(NAN) + E_WARNINGvar_dump(0%0); // DivisiónByZeroErrorintdiv(PHP_INT_MIN, -1); // error aritmético
BC se rompe
El operador de división ya no devolverá false
(que podría haberse reducido silenciosamente a 0 en una operación aritmética)
El operador de módulo ahora generará una excepción con un divisor 0 en lugar de devolver false
RFC: No hay RFC disponible
Al implementar controladores de sesión personalizados, las funciones predicadas de SessionHandlerInterface
que esperan un valor de retorno true
o false
no se comportaron como se esperaba. Debido a un error en la implementación anterior, solo un valor de retorno -1
se consideró falso, lo que significa que incluso si se usó el valor booleano false
para indicar un error, se tomó como un éxito:
<?phpclass FileSessionHandler implementa SessionHandlerInterface { privado $savePath; función abierta($savePath, $sessionName) { devolver falso; // siempre falla } función cerrar(){return true;} función leer($id){} función escribir($id, $datos){} función destruir($id){} función gc($maxlifetime){} }session_set_save_handler(new FileSessionHandler());session_start(); // no causa un error en el código anterior a PHP 7
Ahora, lo anterior fallará con un error fatal. Tener un valor de retorno -1
también seguirá fallando, mientras que 0
y true
seguirán significando éxito. Cualquier otro valor devuelto ahora provocará un error y emitirá un E_WARNING.
BC se rompe
Si se devuelve un valor booleano false
, en realidad fallará ahora
Si se devuelve algo que no sea booleano, 0
o -1
, fallará y provocará que se emita una advertencia.
RFC: Corrige el manejo de los valores de retorno del controlador de sesión personalizado
Los constructores de PHP 4 se conservaron en PHP 5 junto con el nuevo __construct()
. Ahora, los constructores de estilo PHP 4 están quedando obsoletos en favor de tener un solo método ( __construct()
) para ser invocado en la creación de objetos. Esto se debe a que las condiciones sobre si se invocó el constructor estilo PHP 4 causaron una sobrecarga cognitiva adicional a los desarrolladores que también podría resultar confusa para los inexpertos.
Por ejemplo, si la clase se define dentro de un espacio de nombres o si existía un método __construct()
, entonces un constructor de estilo PHP 4 se reconoció como un método simple. Si se definió por encima de un método __construct()
, entonces se emitiría un aviso e_strict, pero aún se reconocería como un método simple.
Ahora en PHP 7, si la clase no está en un espacio de nombres y no hay un método __construct()
presente, el constructor de estilo PHP 4 se utilizará como un constructor, pero se emitirá un E_Depecado. En PHP 8, el constructor de estilo PHP 4 siempre se reconocerá como un método simple y el aviso E_Depreced desaparecerá.
BC se rompe
Los manejadores de errores personalizados pueden verse afectados por la elevación de advertencias E_Depeced. Para solucionar esto, simplemente actualice el nombre del constructor de clase en __construct
.
RFC: eliminar los constructores PHP 4
Cuando se invocaron cualquier funciones basadas en la fecha o el tiempo y no se estableció una zona horaria predeterminada, se emitió una advertencia. La solución fue simplemente establecer la configuración date.timezone
INI en una zona horaria válida, pero esto obligó a los usuarios a tener un archivo php.ini y configurarlo de antemano. Dado que esta era la única configuración que tenía una advertencia adjunta, y de todos modos, por defecto a UTC, la advertencia ahora se ha eliminado.
RFC: elimine la fecha de advertencia de fecha de tiempo.
Las etiquetas alternativas de PHP <%
(y <%=
), %>
, <script language="php">
y </script>
se han eliminado.
BC se rompe
El código que se basó en estas etiquetas alternativas debe actualizarse a las etiquetas de apertura y cierre normales o cortas. Esto se puede hacer manualmente o automatizarse con este script de portada.
RFC: eliminar etiquetas de PHP alternativas
Anteriormente, era posible especificar múltiples declaraciones de bloque default
dentro de una instrucción de conmutación (donde el último bloque default
solo se ejecutó). Esta capacidad (inútil) ahora se ha eliminado y causa un error fatal.
BC se rompe
Cualquier código escrito (o más probablemente generado) que creara declaraciones de conmutador con múltiples bloques default
ahora se convertirá en un error fatal.
RFC: Realice definir múltiples casos predeterminados en un conmutador un error de sintaxis
Anteriormente, era posible especificar parámetros con nombres duplicados dentro de una definición de función. Esta habilidad ahora se ha eliminado y causa un error fatal.
función foo ($ versión, $ versión) {Versión de retorno $; } echo foo (5, 7); // pre Php 7 result7 // Php 7+ Error de resultados de resultado: redefinición del parámetro $ versión en /Redefinition of-Parameters.php
BC se rompe
Los parámetros de la función con nombre duplicado ahora se convertirán en un error fatal.
Se han eliminado los siguientes sapis del núcleo (la mayoría de los cuales se han movido a PECL):
SAPI/AOLSERVER
SAPI/Apache
sapi/apache_hooks
sapi/apache2filter
sapi/caudio
SAPI/Continuidad
SAPI/ISAPI
SAPI/MILTER
SAPI/NSAPI
SAPI/PHTTPD
SAPI/PI3WEB
Sapi/Roxen
sapi/thttpd
sapi/tux
SAPI/WebJames
ext/mssql
ext/mysql
ext/sybase_ct
ext/ereg
RFC: eliminación de sapis y extensiones por parte de muerto o no Php7
Un número hexadecimal fibroso ya no se reconoce como numérico.
var_dump (is_numeric ('0x123')); var_dump ('0x123' == '291'); echo '0x123' + '0x123'; // pre php 7 resultBool (true) bool (true) 582 // php 7+ resultBool (falso) bool (falso) 0
La razón de este cambio es promover una mejor consistencia entre el manejo de números hexadecimales fibrosos en todo el idioma. Por ejemplo, los moldes explícitos no reconocen números hexadecimales fibrosos:
var_dump ((int) '0x123'); // int (0)
En su lugar, los números hexadecimales fibrosos deben validarse y convertirse utilizando la función filter_var()
:
var_dump (filtre_var ('0x123', filtre_validate_int, filter_flag_allow_hex)); // int (291)
BC se rompe
Este cambio afecta la función is_numeric()
y varios operadores, incluyendo ==
, +
, -
, *
, /
, %
, **
, ++
y --
RFC: eliminar el soporte hexadecimal en cadenas numéricas
Se ha eliminado toda la funcionalidad desapercibida, sobre todo:
La extensión MySQL original (ext/mysql)
La extensión ereg (ext/ereg)
Asignación new
por referencia
Llamadas alcanzadas de métodos no estáticos de un $this
contexto incompatible (como Foo::bar()
desde fuera de una clase, donde bar()
no es un método estático)
BC se rompe
Cualquier código que se ejecute con advertencias de deprecación en PHP 5 ya no funcionará (¡fue advertido!)
RFC: eliminar la funcionalidad desaprobada en PHP 7
Los avisos de E_TRICT siempre han sido un área gris en su significado. Estos cambios eliminan esta categoría de error por completo y: elimina el aviso de E_strict, lo cambia a un E_Depreced si la funcionalidad se eliminará en el futuro, la cambia a una E_NOTICE o la promueve a un e_Warning.
BC se rompe
Debido a que E_strict está en la categoría de error de gravedad más baja, cualquier promoción de errores a un E_WARNING puede romper los controladores de errores personalizados
RFC: Reclassify E_strict Avises
password_hash()
Con la introducción de la nueva API de hash de contraseña en PHP 5.5, muchos comenzaron a implementarla y generar sus propias sales. Desafortunadamente, muchas de estas sales se generaron a partir de funciones criptográficamente inseguras como MT_RAND (), lo que hace que la sal sea mucho más débil de lo que se habría generado por defecto. (Sí, siempre se usa una sal cuando hashas contraseñas con esta nueva API.
RFC: no RFC disponible
Los literales octales no válidos ahora causarán un error de análisis en lugar de ser truncados e ignorados en silencio.
Echo 0678; // Error de análisis: literal numérico no válido en ...
BC se rompe
Cualquier literario octal no válido en el código ahora causará errores de análisis
RFC: no RFC disponible
substr()
substr()
ahora devolverá una cadena vacía en lugar de false
cuando la posición de inicio del truncamiento sea igual a la longitud de la cadena:
var_dump (substr ('a', 1)); // pre php 7 resultBool (false) // php 7+ resultados de resultados (0) ""
Sin embargo, substr()
aún puede devolver false
en otros casos.
BC se rompe
El código que verificó estrictamente un valor de retorno bool(false)
ahora puede ser semánticamente inválido
RFC: no RFC disponible
PHP 6 fue la principal versión de PHP que nunca salió a la luz. Se suponía que presentaría un soporte total para Unicode en el núcleo, pero este esfuerzo fue demasiado ambicioso con demasiadas complicaciones que surgieron. Las razones predominantes por las que se omitió la versión 6 para esta nueva versión principal son las siguientes:
Para evitar confusión . Se escribieron muchos recursos sobre PHP 6 y gran parte de la comunidad sabía lo que aparecía en ella. PHP 7 es una bestia completamente diferente con enfoques completamente diferentes (específicamente en el rendimiento) y conjuntos de características completamente diferentes. Por lo tanto, se ha saltado una versión para evitar cualquier confusión o conceptos erróneos en torno a lo que es PHP 7.
Para dejar que los perros durmientes se encuentren . PHP 6 fue visto como una falla y aún queda una gran cantidad de código PHP 6 en el repositorio de PHP. Por lo tanto, fue visto como mejor pasar más allá de la versión 6 y comenzar de nuevo en la próxima versión principal, versión
RFC: Nombre del próximo lanzamiento de PHP