Novedades de PHP 7.4
Lista de novedades que trae la versión 7.4 de PHP

La versión 7.4 de PHP está a la vuelta de la esquina (su lanzamiento está previsto para el 28 de noviembre de este año) y mientras las betas van puliendo las novedades que traerá consigo he considerado interesante escribir un artículo donde recoja las nuevas características de las que dispondremos cuando sea liberada.
De hecho, esta versión trae algunas novedades muy interesantes que no sólo afectan a la seguridad y rendimiento sino que puede que cambien la forma en que desarrollamos ciertas funcionalidades con este lenguaje.
Así que… ¡vamos a verlas!
Introducción
La versión 7.3 de PHP nos trajo un incremento del rendimiento de las aplicaciones (hasta un 10% comparado con PHP 7.2) así como una serie de mejoras sintácticas de cara escribir código más limpio. Todas ellas las podéis encontrar en el artículo que escribí en abril cuando fue liberada:
Con la llegada de PHP 7.4 vemos que esa tendencia se sigue manteniendo de modo que recibiremos nuevas formas de escribir código más limpio y más rápido a la hora de ejecutar tareas.
Además, me atrevería a decir que todas las novedades que trae con sigo PHP 7.4 son más llamativas que las de PHP 7.3 por lo que os recomiendo estar atento y comenzar a familiarizaros con todas ellas de cara a exprimir este lenguaje que gracias a frameworks como Symfony y CMS’s como Wordpress siendo uno de los más populares.
Funciones flecha
Las “arrow functions” llegan por fin a PHP algo que seguro agradecéis aquellos que también programéis en Javascript. Estas funciones, también conocidas como “short closures” permiten escribir funciones cortas de una forma menos “verbosa”.
Supongamos que tenemos el siguiente código:
$prices = array_map(function (Product $product) {
return $product->getPrice();
}, $products);
Con PHP 7.4 podemos convertirlo en:
$prices = array_map(fn($product) => $product->getPrice(), $products);
Entre las principales características de esta nueva sintaxis tenemos:
- Es necesario que comiencen con
fn
(esta es la principal diferencia con Javascript donde no es necesario “marcarlas” con un prefijo). - Sólo pueden tener una expresión que es considerada el valor de retorno de la función, es decir, no podemos emplear llaves y declarar explícitamente el
return
. Seguramente esta sea la restricción más llamativa pero en palabras de Nikita Popov, el creador de la RFC, la ventaja de emplear “arrow functions” en PHP no es mucha si necesitamos escribir funciones de más de una línea que terminarán por ser más verbosas de una forma u otra. - Tanto los argumentos como el valor de retorno pueden estar tipados, por ejemplo:
$prices = array_map(fn(Product $product): float => $product->getPrice(), $products);
- El operador
spread
está permitido. - Y es posible pasar por referencia los argumentos y devolver por referencia los valores de retorno.
- A diferencia de las
closures
normales, no es necesario emplear la palabra claveuse
para acceder a variables dentro del “scope” superior:
$multiplier = 5; array_map(fn($x) => $x * $multiplier, $numbers);
Typed class properties
A partir de PHP 7.4 podremos tipar las propiades de nuestras clases:
class User { public string $name; public ?int $age; public ContactInfo $contactInfo;}
Las principales características de esta novedad son:
- Solo está permitido tipar aquellas propiedades que tengan un modificador de acceso (
public
,protected
oprivate
). - No es posible emplear ni
void
nicallable
para tipar propiedades. - A partir de ahora es necesario prestar atención a las variables no inicializadas que están tipadas. Por ejemplo, este código es válido:
class Foo {
public string $bar;
} $foo = new Foo;
Sin embargo, en el momento en que escribamos:
var_dump($foo->bar);
Obtendremos un Fatal Error
indicándonos que no podemos acceder a la propiedad $bar
sin antes inicializarla:
Fatal error: Uncaught Error: Typed property Foo::$bar must not be accessed before initialization
- Si empleamos
unset
sobre una propiedad tipada, ésta pasará a ser marcada comouninitialized
a diferencia de lo que sucede con las no tipadas, que pasan a tener el valornull
. - En el caso de propiedades escalares, es posible proveer un valor por defecto:
class User {
public int $age = 32;
public ?string $name = null;
public array $telephones = ['xxxx', 'bbbbb'];
}
“Type variance” mejorada en el retorno de funciones
Con la llegada de PHH 7.4 se ha introducido una mejora en los tipos de retorno de las funciones, permitiéndonos realizar lo siguiente:
class Parent {};
class Child extends Parent {};class Foo
{
public function covariant(): ParentType {};
}class Bar extends Foo
{
public function covariant(): ChildType {};
}
Es decir, una clase hija puede sobrescribir el tipo de retorno de un método de la clase padre si ese tipo extiende del tipo que devuelve el padre.
Esto se conoce en el argot como “covariant return types”.
Además, también se han introducido “contravariant arguments” de modo que:
class Parent {};
class Child extends Parent {};class Foo
{
public function contravariant(Child $value) {};
}class Bar extends Foo
{
public function contravariant(Parent $value) {};
Lo cual cumple con el principio de sustitución de Liskov:
If
S
is a subtype ofT
, then objects of typeT
may be replaced with objects of typeS
Nuevo operador: Null coalescing assignment operator
Al “null coalescing operator” se le suma un nuevo operador que simplifica aún más ese tipo de asignaciones de modo que podemos pasar de escribir:
$someArray['key'] = $someArray['key'] ?? 'foo';
A:
$someArray['key'] ??= 'foo';
Operador spread para arrays
Otra de las novedades sintáticas que trae PHP 7.4 consigo es el operador “spread” para arrays, algo con lo que seguro que ya estáis familiarizados si trabajáis con Javascript regularmente.
Este nuevo operador nos permitirá escribir código como el siguiente:
$foo = [1, 2, 3];$bar = ['a', 'b', 'c'];$result = [0, ...$foo, ...$bar, 'd'];// 0, 1, 2, 3, 'a', 'b', 'c', 'd'
Eso sí, de momento sólo es posible usarlo con arrays que tengan claves numéricas por lo que habrá que esperar a una siguiente versión para emplear este operador con arrays asociativos.
Preloading
Ésta es probablemente la novedad que más bombo ha recibido desde que fue anunciada pese a ser una característica de bajo nivel. Sin embargo su inclusión traerá consigo mejoras de rendimiento sustanciales.
A modo de resumen esta nueva característica permite al servidor cargar los archivos PHP en memoria al principio de modo que estén permanentemente disponibles para todas las “requests” posteriores a la carga. Evidentemente esto supone una mejora muy significativa en la velocidad a la que se ejecutarán las peticiones pero que sin embargo nos obligará a reiniciar el servidor cada vez que modifiquemos el código fuente.
Estarás pensando que esta característica es muy similar a OPCache sin embargo no es exactamente lo mismo. OPCache lo que hace escoger los archivos fuente de PHP y compilarlo a “opcodes” los cuales son almacenados en disco. Estos “opcodes” son representaciones a bajo nivel del código de tu aplicación que pueden ser interpretados de forma más rápida en tiempo de ejecución puesto que es como si ya estuvieran en “lenguaje máquina” por lo que no es necesario que PHP los “traduzca”.
Además, los archivos generados de este modo por OPCache no tienen conocimiento de otros archivos. Es decir, si la clase Bar
extiende de Foo
, en tiempo de ejecución será necesario “linkarlas”.
Finalmente, OpCache tiene un mecanismo que comprueba si ha habido modificaciones en los archivos fuentes de cara a invalidar la cache en el caso de detectar cambios.
Es aquí donde se encuentra la principal diferencia con Preloading de PHP 7.4. Esta característica no sólo compila los archivos a “opcode” sino que también linka las clases relacionadas, “traits” e interfaces y lo almacena en memoria de modo que cuando llega una petición ya lo tiene disponible.
Para que preloading funcione, es necesario decirle al servidor qué archivos tiene que cargar en memoria. Esto se realiza con un simple script de PHP el cual linkaremos desde el archivo php.ini
empleando la directiva opcache.preload
:
opcache.preload=/path/to/project/preload.php
De este modo, todos los archivos que queramos que sean “precargados” tendremos que pasarlos a través de este script por medio de la instrucción opcache_compile_file()
:
//preload.php$files = ['file1.php', 'file2.php'];foreach ($files as $file) {
opcache_compile_file($file);
}
¡Ojo! Si queremos precargar clases en memoria debemos asegurarnos de que también cargamos sus dependencias (interfaces, “traits” y clases padre”) dado que si no recibiremos el siguiente error:
Can't preload unlinked class Foo
Unknown parent Bar
Esto provoca que tengamos que prestar especial atención a la generación de este script de cara a no caer en este tipo de fallos de dependencias ausentes (algo que puede suceder de forma muy fácil en el momento en que trabajemos con un framework como Symfony). Por eso es que ya hay varios equipos trabajando en herramientas que automaticen la generación de este script empleando composer de modo que se pueda añadir a este archivo la configuración de nuestro preload.
En cuanto a la mejora de rendimiento Ben Morel compartió algunas benchmarks que podéis consultar desde aquí:
Conclusión
Como veis, PHP 7.4 trae gran cantidad de mejoras por lo que os recomiendo que poco a poco os comencéis a familiarizar con ellas de cara adoptarlas en el código que escribáis.
Mientras llega noviembre iré actualizando este artículo con los cambios que vayan surgiendo en las últimas betas. ¡Espero que os haya servido!
¿Quieres recibir más artículos como este?
Si te ha gustado este artículo te animo a que te suscribas a la newsletter que envío cada domingo con publicaciones similares a esta y más contenido recomendado: 👇👇👇