<?php
class foo { static $bar = 'baz'; }
var_dump('foo'::$bar);
?>
if < php7.0
then we will receive a syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
but php7 returns string(3) "baz"
I think it's not documented anywhere
Las
declaraciones de tipo escalar
son de dos tipos: coercitivo (por defecto) y estricto. Ahora se pueden forzar
los siguientes tipos para parámetros (tanto coercitiva como estrictamente): cadenas de caracteres
(string), números enteros (int
), números
decimales (float), y booleanos (bool
). Estos
se añaden a los tipos introducidos en PHP 5: nombres de clases, interfaces,
arrays y callables.
<?php
// Modo coercitivo
function sumaDeEnteros(int ...$enteros)
{
return array_sum($enteros);
}
var_dump(sumaDeEnteros(2, '3', 4.1));
El resultado del ejemplo sería:
int(9)
Para habilitar el modo estricto se debe colocar una simple directiva declare
al
inicio del fichero. Esto siginfica que la rigurosidad de la tipificación de escalares se
configura en función de cada fichero. Esta directiva no solamente afecta a las declaraciones
de tipo de parámetros, sino también al tipo de devolución de una función (véanse las
declaraciones de tipo de devolución),
a funciones internas de PHP, y a funciones de extensiones
cargadas.
Se puede encontrar la documentación completa y ejemplos de las declaraciones de tipo escalar en la referencia de declaraciones de tipo.
PHP 7 añade soporte para declaraciones de tipo de devolución. Similarmente a las declaraciones de tipo de argumento, las declaraciones de tipo de devolución especifican el tipo del valor que será devuelto por una función. Están disponibles los mismos tipos tanto para las declaraciones de tipo de devolución como para las declaraciones de tipo de argumento.
<?php
function sumarArrays(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
print_r(sumarArrays([1,2,3], [4,5,6], [7,8,9]));
El resultado del ejemplo sería:
Array ( [0] => 6 [1] => 15 [2] => 24 )
Se puede encontrar la documentación completa y ejemplos de las declaraciones de tipo de devolución en la referencia de las declaraciones de tipo de devolución.
El operador de fusión de null (??
) se ha añadido como
aliciente sintáctico para el caso común de la necesidad de utilizar un operador ternario junto
con isset(). Devuelve su primer operando
si existe y no es null
; de lo contrario devuelve su segundo operando.
<?php
// Obntener el valor de $_GET['usuario'] y devolver 'nadie'
// si no existe.
$nombre_usuario = $_GET['usuario'] ?? 'nadie';
// Esto equivale a:
$nombre_usuario = isset($_GET['usuario']) ? $_GET['usuario'] : 'nadie';
// La fusión se puede encadenar: esto devolverá el primer
// valor definido de $_GET['usuario'], $_POST['usuario'],
// y 'nadie'.
$nombre_usuario = $_GET['usuario'] ?? $_POST['usuario'] ?? 'nadie';
?>
El operador nave espacial se emplea para comparar dos expresiones. Devuelve -1, 0 o 1 cuando $a es respectivamente menor, igual, o mayor que $b. Las comparaciones se realizan según las reglas de comparación de tipos usuales de PHP.
<?php
// Números enteros
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Numeros decimales
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Cadenas de caracteres
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>
Ahora se pueden definir constantes de array con
define(). En PHP 5.6, solamente se podían definir con
const
.
<?php
define('ANIMALES', [
'perro',
'gato',
'pájaro'
]);
echo ANIMALES[1]; // imprime "gato"
?>
Se ha añadido soporte para clases anónimas mediante new
clase
. Estas se pueden utilizar en lugar de definiciones de clases completas
para objetos desechables:
<?php
interface Logger {
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());
?>
El resultado del ejemplo sería:
object(class@anonymous)#2 (0) { }
La documentación completa se puede encontrar en la referencia de clases anónimas.
Esta sintaxis toma un punto de código de Unicode en forma hexadecimal, e imprime ese punto de código en UTF-8 a un string con entrecomillado doble o a un heredoc. Se acepta cualquier punto de código válido, siendo los ceros iniciales opcionales.
echo "\u{aa}";
echo "\u{0000aa}";
echo "\u{9999}";
El resultado del ejemplo sería:
ª ª (lo mismo que antes pero con ceros iniciales opcinales) 香
Closure::call() es una manera más eficiente y abreviada de vincular temporalmente un ámbito de objeto a un cierre e invocarlo.
<?php
class A {private $x = 1;}
// Código anterior a PHP 7
$getX = function() {return $this->x;};
$getXCB = $getX->bindTo(new A, 'A'); // cierre intermedio
echo $getXCB();
// Código de PHP 7+
$getX = function() {return $this->x;};
echo $getX->call(new A);
El resultado del ejemplo sería:
1 1
Esta característica busca el proporcionar una mejor seguridad al deserializar objetos en datos no fiables. Previene de posibles inyecciones de código al capacitar al desarrollador a crear listas blancas de clases que deden ser deserializadas.
<?php
// convertir todos los objetos a un objeto __PHP_Incomplete_Class
$data = unserialize($foo, ["allowed_classes" => false]);
// convertir todos los objetos a un objeto __PHP_Incomplete_Class excepto a los de MiClase y MiClase2
$data = unserialize($foo, ["allowed_classes" => ["MiClase", "MiClase2"]]);
// comportamiento predeterminado (lo mismo que omitir el segundo argumento) que acepta todas las clases
$data = unserialize($foo, ["allowed_classes" => true]);
La nueva clase IntlChar busca exponer funcionalidad adicional de ICU. La clase en sí define varios métodos estáticos y constantes que se pueden emplear para manipular caracteres Unicode.
<?php
printf('%x', IntlChar::CODEPOINT_MAX);
echo IntlChar::charName('@');
var_dump(IntlChar::ispunct('!'));
El resultado del ejemplo sería:
10ffff COMMERCIAL AT bool(true)
Para utilizar esta clase debe estar instalada la extensión Intl.
Las previsiones son una mejora retrocompatible con la antigua función assert(). Con ellas se pueden realizar afirmaciones sin coste en código de producción, proporcionando la capacidad de lanzar excepciones personalizadas cuando la afirmación falla.
Mientras que la API antigua se siguie manteniendo por compatibilidad, assert() ahora es un constructor de lenguaje, permitiendo que el primer parámetro sea una expresión en lugar de solamente un string a evaluar o un valor de tipo bool a probar.
<?php
ini_set('assert.exception', 1);
class ErrorPersonalizado extends AssertionError {}
assert(false, new ErrorPersonalizado('Un mensaje de error'));
?>
El resultado del ejemplo sería:
Fatal error: Uncaught ErrorPersonalizado: Un mensaje de error
Se pueden encontrar los detalles completos de esta característica, incluyendo cómo configurarla tanto en entornos de desarrollo como de producción, en la sección de previsiones de la referencia de assert().
use
en grupo
Las clases, funciones y constantes que se importen desde el mismo namespace
ahora pueden ser agrupadas en una única sentencia use
.
<?php
// Código anterior a PHP 7
use un\espacioDeNombres\ClaseA;
use un\espacioDeNombres\ClaseB;
use un\espacioDeNombres\ClaseC as C;
use function un\espacioDeNombres\fn_a;
use function un\espacioDeNombres\fn_b;
use function un\espacioDeNombres\fn_c;
use const un\espacioDeNombres\ConstA;
use const un\espacioDeNombres\ConstB;
use const un\espacioDeNombres\ConstC;
// código de PHP 7+
use un\espacioDeNombres\{ClaseA, ClaseB, ClaseC as C};
use function un\espacioDeNombres\{fn_a, fn_b, fn_c};
use const un\espacioDeNombres\{ConstA, ConstB, ConstC};
?>
Esta característica se basa en la funcionalidad de los generadores introducida en PHP 5.5.
Habilita a la sentencia return
para utilizarla dentro de
un generador para que pueda devolver una expresión final (la devolución por
referencia no está permitida). Este valor se puede obtener empleando el nuevo
método Generator::getReturn()
, el cual solamente se puede utilizar
una vez que el generador ha finalizado de producir valores.
<?php
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;
El resultado del ejemplo sería:
1 2 3
La capacidad de devolver explícitamente un valor final desde un generador (quizá desde una forma de computación de corutina) es útil debido a que puede ser específicamente manejado por el código del cliente que ejecuta el generador. Esto es mucho más simple que forzar al código del cliente a comprobar primero si el valor final se ha generado y luego, si es asi, manejar dicho valor específicamente.
Los generadores ahora pueden delegar a otro generador,
objeto Traversable o array
de forma automática, sin la necesidad de escribir «clichés» en el generador
más externo con la construcción yield from
.
<?php
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
function gen2()
{
yield 3;
yield 4;
}
foreach (gen() as $val)
{
echo $val, PHP_EOL;
}
?>
El resultado del ejemplo sería:
1 2 3 4
La nueva función intdiv() realiza una división entera de sus operandos y la devuelve.
<?php
var_dump(intdiv(10, 3));
?>
El resultado del ejemplo sería:
int(3)
session_start() ahora acepta un array de opciones que sobrescriben las directivas de configuración de sesiones establecidas normalmente en php.ini.
Estas opciones también se han ampliado para admitir
session.lazy_write, la cual está
activada de forma predeterminada y causa que PHP solamente sobrescriba cualquier fichero de sesión si los
datos de sesión han cambiado, y read_and_close
, la cual es
una opción que se puede pasar solo a session_start() para
indicar que los datos de sesión deberían ser leídos y luego la sesión debería
ser cerrada inmediatamente sin cambios.
Por ejemplo, para establecer
session.cache_limiter a
private
e inmediatamente cerrar la sesión después de
leerla:
<?php
session_start([
'cache_limiter' => 'private',
'read_and_close' => true,
]);
?>
Con la nueva función preg_replace_callback_array(), el código escrito es más claro al emplear la función preg_replace_callback(). Antes de PHP 7, las retrollamadas que necesitaban ser ejecutadas por cada expresión regular requerían que la función de retrollamda fuera contaminada con muchas ramificaciones.
Ahora, las retrollamadas se pueden registrar para cada expresión regular usando un array asociativo, donde la clave es una expresión regular y el valor es una retrollamada.
Se han añadido dos nuevas funciones para generar números enteros y cadenas de caractéres criptográficamente seguros de una forma multiplataforma: random_bytes() y random_int().
Anteriormente, no se garantizaba que list() operase correctamente con objetos que implementasen ArrayAccess. Esto ha sido arreglado.
(clone $foo)->bar()
.
<?php
class foo { static $bar = 'baz'; }
var_dump('foo'::$bar);
?>
if < php7.0
then we will receive a syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
but php7 returns string(3) "baz"
I think it's not documented anywhere
A good rule of thumb for remembering what the spaceship operator expression returns is to replace the spaceship operator with a minus sign (-). If the result is negative, 0 or positive, the expression will return -1, 0 or 1 respectively.
Example:
<?php
echo 5 <=> 8; // 5 - 8 = -3, prints -1
echo 2 <=> 2; // 2 - 2 = 0, prints 0
echo 4 <=> 2; // 4 - 2 = 2, prints 1
In php 7.0 it's possible to curry functions in a way that's similar to JavaScript.
<?php
// A curried function
function add($a) {
return function($b) use ($a) {
return $a + $b;
};
}
// Invoking curried function in PHP 7
$result = add(10)(15);
var_dump($result); // int 25
?>
Currying in this way is not possible in php 5.6.
Currying was possible in php 5.6. But in php 7.0 it is now possible to invoke a curryied function with a one liner.
<?php
// A curried function
function add($a) {
return function($b) use ($a) {
return $a + $b;
};
}
// Invoking a curried function in PHP 7
$result = add(10)(15);
var_dump($result); // int 25
// Invoking a curried function in PHP 5.6
$add10 = add(10);
$result = $add10(15);
var_dump($result); // int 25
?>
Be careful on performing null coalesce on typecasted properties. Enclose them in parenthesis
<?php
$foo = new StdClass;
//(int) 23
$bar = $foo->bas ?? 23;
var_dump($bar);
$foo = new StdClass;
//(int) 23
$bar = (int) ($foo->bas ?? 23);
var_dump($bar);
$foo = new StdClass;
$bar = (int) $foo->bas ?? 23;
//Notice: Undefined property: stdClass::$bas
var_dump($bar);
$a = ''; // or 0 or false
$b = $a ?? 'a';
// $b is '' or 0 or false
$c = $a ?: 'a';
// $c is 'a'
It is worth nothing that the following code just works in PHP 7.4:
```
function nullOrDefault($x = null)
{
$x ??= 3222;
return $x;
}
```