Novedades de PHP 7.4

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

Image for post
Image for post
Novedades de PHP 7.4

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 clave use 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 o private ).
  • No es posible emplear ni void ni callable 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 como uninitialized a diferencia de lo que sucede con las no tipadas, que pasan a tener el valor null .
  • 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 of T, then objects of type Tmay be replaced with objects of type S

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: 👇👇👇

Written by

Entre paseo y paseo con Simba desarrollo en Symfony y React

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store