PHP 7.4, la próxima publicación pequeña de PHP 7, ha sido publicada a partir del 28 de noviembre de 2019. Así que es momento que nos adentremos en algunas de las nuevas y emocionantes adiciones y nuevas funciones que harán a PHP mucho más rápido y confiable.

Actualización: PHP 8.1 (versión oficial) ya está disponible para todos los clientes de Kinsta. PHP 7.4 ya no es soportado por Kinsta. Ten en cuenta que soportamos versiones de PHP 8.0, 8.1, 8.2 y 8.3.

Incluso si PHP 7.4 incrementa de forma significativa el desempeño y mejora la legibilidad del código, PHP 8 será el logro más importante para el desempeño de PHP, ya que la propuesta para la inclusión de JIT ya ha sido aprobada.

De todas formas, hoy mismo veremos algunas de las funciones más interesantes y cambios que estamos esperando con PHP 7.4. Para que conste, estas fueron las fechas importantes para la versión 7.4:

  • 6 de Junio de 2019: PHP 7.4 Alpha 1
  • 18 de Julio de 2019: PHP 7.4 Beta 1 – Función de Congelamiento
  • 28 de Noviembre de 2019: PHP 7.4 Lanzamiento GA

Puede ver la lista completa de funciones y adiciones en la página oficial de RFC.

¿Qué Hay de Nuevo en PHP con PHP 7.4?

En este artículo cubriremos los cambios y funciones generales que deberían ser agregadas al idioma con el lanzamiento final de PHP 7.4:

Olvida array_merge: PHP 7.4 Trae un Operador de Esparcimiento en la Expresión de Matriz

Disponible a partir de PHP 5.6, el desempacado argumentado es una sintaxis para desempacar matrices y Traversables en listas argumentales. Para desempacar una matriz o una Traversable, tiene que tener antes … (3 puntos), como se muestra en el siguiente ejemplo:

function test(...$args) { var_dump($args); }
test(1, 2, 3);

Ahora este RFC de PHP 7.4 propone extender esta función a definiciones de matriz:

$arr = [...$args];

El primer beneficio declarado del Operador de Esparcimiento en expresión de matriz es su desempeño. De hecho, el doc del RFC declara:

El operador de Esparcimiento debería tener un mejor desempeño que array_merge. Esto no sólo porque el operador de esparcimiento es una estructura de lenguaje mientras que el array_merge es una función, sino también porque la optimización de compilación de tiempo puede desempeñarse para matrices constantes.

Una ventaja significativa del Operador de Esparcimiento es que este tiene soporte para cualquier objeto traversable, mientras que la función array_merge sólo tiene soporte para relés.

Aquí tenemos un ejemplo de un desempaque de argumento en la expresión de matriz:

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
var_dump($fruits);

Si usted utiliza este código con PHP 7.3 o anterior, PHP mostrará un Error de análisis:

Parse error: syntax error, unexpected '...' (T_ELLIPSIS), expecting ']' in /app/spread-operator.php on line 3

En lugar, PHP 7.4 mostraría una matriz:

array(5) {
	[0]=>
	string(6) "banana"
	[1]=>
	string(6) "orange"
	[2]=>
	string(5) "apple"
	[3]=>
	string(4) "pear"
	[4]=>
	string(10) "watermelon"
}

El RFC declara que podemos expandir la misma matriz varias veces. Además de esto, podemos utilizar la sintaxis del Operador de Esparcimiento en cualquier parte en la matriz, ya que los elementos normales pueden ser agregados antes o después del operador de esparcimiento. Así que el siguiente código funcionaría como podríamos esperar:

$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];
$arr3 = [...$arr1, ...$arr2];
$arr4 = [...$arr1, ...$arr3, 7, 8, 9];

También es posible desempacar matrices regresadas por una función directamente en una nueva matriz:

function buildArray(){
	return ['red', 'green', 'blue'];
}
$arr1 = [...buildArray(), 'pink', 'violet', 'yellow'];

PHP 7.4 saca la siguiente matriz:

array(6) {
	[0]=>
	string(3) "red"
	[1]=>
	string(5) "green"
	[2]=>
	string(4) "blue"
	[3]=>
	string(4) "pink"
	[4]=>
	string(6) "violet"
	[5]=>
	string(6) "yellow"
}

También podemos usar el generador de sintaxis:

function generator() {
	for ($i = 3; $i <= 5; $i++) {
		yield $i;
	}
}
$arr1 = [0, 1, 2, ...generator()];

Pero no tenemos permitido desempacar matrices pasadas por referencia. Considere el siguiente ejemplo:

$arr1 = ['red', 'green', 'blue'];
$arr2 = [...&$arr1];

Si intentáramos desempacar una matriz por referencia, PHP nos mostraría el siguiente error de análisis:

Parse error: syntax error, unexpected '&' in /app/spread-operator.php on line 3

De cualquier forma, si los elementos de la primera matriz son almacenados por referencia, estos son almacenados por referencia en la segunda matriz también. Aquí tenemos un ejemplo:

$arr0 = 'red';
$arr1 = [&$arr0, 'green', 'blue'];
$arr2 = ['white', ...$arr1, 'black'];

Y esto es lo que obtenemos con PHP 7.4:

array(5) {
	[0]=>
	string(5) "white"
	[1]=>
	&string(3) "red"
	[2]=>
	string(5) "green"
	[3]=>
	string(4) "blue"
	[4]=>
	string(5) "black"
}

La propuesta del Operador de Esparcimiento pasó con 43 votos a 1.

Función de Flechas 2.0 (Cierres Cortos)

En PHP, las funciones anónimas son consideradas bastante verbosas y difíciles de implementar y mantener. Este RFC propone la introducción de sintaxis más cortas y claras de las funciones de flecha (o cierres más cortos), que debería permitirnos dejar mucho más claro nuestro código de PHP.

Considere el siguiente ejemplo:

function cube($n){
	return ($n * $n * $n);
}
$a = [1, 2, 3, 4, 5];
$b = array_map('cube', $a);
print_r($b);

PHP 7.4 nos permite utilizar una sintaxis más concisa, y la función anterior podría ser rescrita de esta forma:

$a = [1, 2, 3, 4, 5];
$b = array_map(fn($n) => $n * $n * $n, $a);
print_r($b);

Actualmente, las funciones anónimas (cierres) pueden heredar variables definidas en el esquema padre gracias a la construcción de lenguaje use, como se muestra a continuación:

$factor = 10;
$calc = function($num) use($factor){
	return $num * $factor;
};

Pero con PHP 7.4, las variables definidas en el esquema padre son implícitamente capturadas por valor (unión de esquema implícito por valor). Así que podemos escribir funciones completas como se ve arriba en una sola línea:

$factor = 10;
$calc = fn($num) => $num * $factor;

La variable definida en el esquema padre puede ser usada en la función de flecha exactamente como si estuviéramos usando use($var), y no es posible modificar una variable a partir del esquema padre.

La nueva sintaxis es una gran mejora al lenguaje ya que nos permite utilizar crear un código más legible y de fácil mantenimiento. También podemos utilizar tipos de parámetro y de retorno, valores base, listas de argumento de longitud variable (funciones variables), podemos pasar y regresar por referencia, etc. Al final, los cierres cortos también pueden ser usados en métodos de clase, y pueden darle uso a la variable $this como cualquier cierre regular.

Reste RFC ha sido aprobado con 51 votos contra 8, así que podemos esperar que sea parte de las adiciones a PHP 7.4.

Operador de Asignación de Unión Nula

Junto con PHP 7, el operador de unión (??) llega a ser bastante útil cuando necesitamos un operador ternario en conjunto con isset(). Este regresa la primera operación si existe o no NULL. De otra forma, este regresa la segunda operación. Aquí tenemos un ejemplo:

$username = $_GET['user'] ?? 'nobody';

Lo que hace este código es bastante directo. Este toma la petición de parámetro y establece un valor base si este no existe. El significado de está línea es claro, ¿pero qué tal si tuviéramos nombres variables como en este ejemplo del RFC?

$this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value';

A la larga, este código podría ser difícil de mantener. Así que, con la idea de ayudar a los desarrolladores a escribir un código más intuitivo, este RFC propone la introducción de un operador de asignación de unión nula (??=). Así que, en lugar de escribir el código previo, podríamos escribir lo siguiente:

$this->request->data['comments']['user_id'] ??= 'value';

Si el valor del parámetro de la izquierda es null, entonces el valor del parámetro a mano derecha es usado.Ahora dése cuenta que, mientras que el operador de unión es un operador de comparación, el ??= es un operador de asignación.

Esta propuesta ha sido aprobada por 37 votos contra 4.

Propiedades Tipeadas 2.0

Las declaraciones de tipo argumento, o tipos de indicios, permite especificar el tipo de variable que se espera que pase a una función o a un método de clase. Los tipos de indicios son una función disponible a partir de PHP 5, y desde PHP 7.2 podemos usarlas con el tipo de dato object. Ahora PHP 7.4 trae este indicio de tipo un paso más adelante al agregar soporte para declaraciones de tipo de propiedad de primera clase. Aquí tenemos un ejemplo básico:

class User {
	public int $id;
	public string $name;
}

Todos los tipos son soportados, con excepción de void y callable:

public int $scalarType;
protected ClassName $classType;
private ?ClassName $nullableClassType;

Este RFC explica la razón por la cual void y callable no son soportados:

El tipo void no está soportado, porque no es útil y tiene muchas semánticas que no son claras.

El tipo callable no está soportado, porque su comportamiento es dependiente al contexto.

Así que podemos utilizar de forma segura boolintfloatstringarrayobjectiterableselfparent, cualquier clase o nombre de interfaz, y tipos nulos (?type)

Los tipos pueden ser usados en propiedades estáticas:

public static iterable $staticProp;

También son permitidas con la notación var:

var bool $flag;

Es posible establecer valor de propiedad bases, que por supuesto, deben ser iguales al tipo de propiedad declarada, pero sólo las propiedades anuladas pueden tener un valor null base:

public string $str = "foo";
public ?string $nullableStr = null;

El mismo tipo aplica a todas las propiedades en una sola declaración:

public float $x, $y;

¿Qué pasa si cometemos un error en el tipo de propiedad? Considere el siguiente código:

class User {
	public int $id;
	public string $name;
}

$user = new User;
$user->id = 10;
$user->name = [];

En el código anterior, hemos declarado un tipo de propiedad de string, pero establecimos una matriz como el valor de propiedad. En dicho escenario, obtenemos el siguiente error Fatal:

Fatal error: Uncaught TypeError: Typed property User::$name must be string, array used in /app/types.php:9

Este RFC ha sido aprobado con 70 votos contra 1.

 

Referencias Débiles (Weak References)

Con este RFC, PHP 7.4 introduce la clase WeakReference, el cual le permite a los programadores retener una referencia a un objeto que no prevenga que el objeto mismo sea destruido.

Actualmente PHP tiene soporte para Weak References al usar una extensión como pecl-weakref. De todas formas, la nueva API es diferente a la clase WeakRef documentada.

Aquí tenemos un ejemplo del autor de esta propuesta, Nikita Popov:

$object = new stdClass;
$weakRef = WeakReference::create($object);

var_dump($weakRef->get());
unset($object);
var_dump($weakRef->get());

El primer var_dump imprime object(stdClass)#1 (0) {}, mientras que el segundovar_dump imprime NULL, mientras el objeto referido ha sido destruido.

Este RFC pasó con 28 votos contra 5.

Tipos de Retorno de Variación y Parámetro de Contra Variante

La varianza es la propiedad de jerarquías de clase describiendo como los tipos de un constructor de tipo afectan los subtipos. En general, un constructor de tipo puede ser:

  • Invariante: si el tipo del súper tipo limita al tipo del subtipo.
  • Covariante: si el orden de los tipos es preservado (tipos son ordenados del más específico al más genérico).
  • Contravariante: si este revierte el orden (los tipos son ordenados del más genérico al más específico).

Actualmente, PHP tiene parámetros principalmente invariados y tipos de retorno, con algunas excepciones. Este RFC propone permitir covarianza y contravarianza en los tipos de parámetros y tipos de retorno, también proveyendo varios ejemplos del código.

Aquí tenemos un tipo de retorno covariante:

interface Factory {
	function make(): object;
}

class UserFactory implements Factory {
	function make(): User;
}

Y aquí tenemos un ejemplo del tipo de parámetro contracovariante:

interface Concatable {
	function concat(Iterator $input); 
}
 
class Collection implements Concatable {
	// accepts all iterables, not just Iterator
	function concat(iterable $input) {/* . . . */}
}

Vea el RFC para tener una idea más detallada de la covarianza y contravarianza en PHP 7.4.

Este RFC pasó con 39 votos contra 1.

Precarga

Esta propuesta de Dmitry Stogov es una de nuestras favoritas porque esta debería traer una mejora importante en el desempeño. La Precarga es el proceso de cargar bibliotecas y frameworks en el OPCache en la inicialización del módulo (lea más sobre el ciclo de vida de PHP).

Ciclo de vida de PHP
Ciclo de vida de PHP (fuente de la imagen: PHP Internals)

Así es como funciona la precarga según Dmitry:

En el inicio del servidor – antes de que empiece a funcionar el código de cualquier aplicación – podemos cargar un cierto conjunto de archivos PHP en la memoria – y lograr que sus contenidos estén “permanentemente disponibles” a todas las peticiones subsecuentes que serán servidas por el servidor. Todas las funciones y clases definidas en estos archivos estarán disponibles a peticiones fuera de la caja, exactamente como entidades internas.

Estos archivos son cargados en el inicio del servidor, son ejecutados antes de cualquier aplicación y se mantienen disponibles para cualquier petición futura. Esto es fantástico en términos de desempeño.

La precarga es controlada por una directiva php.ini específica: opcache.preload.

Esta directiva específica a que un script de PHP sea compilado y ejecutado durante el inicio del servidor. Este archivo puede ser usado para precargar archivos adicionales, sea incluyéndolos o a través de la función opcache_compile_file()(lea más sobre la documentación de PHP).

Pero aquí tenemos un aspecto negativo. De hecho, el RFC declara de forma explicita:

Los archivos precargados permanecen en el caché de la memoria opcache para siempre. La modificación de sus archivos fuentes correspondientes no tendrán efecto alguno sin que se reinicie de nuevo el servidor.

Sin embargo, todas las funciones definidas en los archivos precargados serán permanentemente cargadas en la función PHP y tablas de clase, y permanecerán disponibles para cada petición futura. Esto llevará a una mejora en el desempeño, incluso si estas mejoras podrían ser considerablemente variables.

Puede leer más sobre las limitaciones y expectativas de la precarga en la página oficial de la Precarga del RFC.

Nuevos Mecanismos en Serie Personalizada de Objetos

Esta es otra propuesta de Nikita Popov, aprobada por una gran mayoría de votos.

Actualmente, tenemos dos mecanismos diferentes para la serie personalizada de objetos en PHP:

  • Los métodos mágicos de __sleep()y __wakeup().
  • La interfaz Serializable

De acuerdo a Nikita, estas dos opciones tienen problemas que llevan a un código complejo y nada confiable. Uno puede adentrarse más a este tema en el RFC. Aquí sólo he mencionado que el nuevo mecanismo de serie debería prevenir estos problemas al proveer dos nuevos métodos mágicos, __serialize() y __unserialize(), que combinan estos dos mecanismos existentes.

Esta propuesta pasó con 20 votos contra 7.

Depreciaciones

Las siguientes funciones/funcionalidades serán depreciadas con PHP 7.4. para ver una lista más comprensiva de las depreciaciones. Lea las Notas de Actualización de PHP 7.4.

Cambie el Precedente del Operador de Concatenación

Actualmente, en PHP los operadores aritméticos “+” y “-“, y el operador de string “.” son puestos como asociativos y tienen el mismo precedente (lea más sobre el Precedente del Operador).

Como ejemplo, considere la siguiente línea:

echo "sum: " . $a + $b;

En PHP 7.3, este código produce la siguiente advertencia:

Warning: A non-numeric value encountered in /app/types.php on line 4

Esto es por que la concatenación es valorada de izquierda a derecha. Es lo mismo que escribir el siguiente código:

echo ("sum: " . $a) + $b;

Este RFC propone cambiar el precedente de los operadores, dando al “.” un precedente menor que a los operadores “+” y “-“, así que las adiciones y sustracciones podrían siempre desempeñarse antes de la concatenación de string. Esta línea de código debería ser equivalente a lo siguiente:

echo "sum: " . ($a + $b);

Esta es una propuesta de dos pasos:

  • Empezando desde la versión 7.4, PHP debería emitir un aviso de depreciación cuando se encuentre una expresión sin paréntesis con un “+” , “-“ y “.”.
  • El cambio real del precedente de estos operadores debería ser agregado con PHP 8.

Ambas propuestas han sido aprobadas con una gran mayoría de votos.

Operador ternario de depreciación asociativa a la izquierda

En PHP el operador ternario, a diferencia de muchos otros lenguajes, es asociativo a la izquierda. De acuerdo a Nikita Popof, esto puede ser confuso para los programadores que cambien a distintos lenguajes.

Actualmente, en PHP el siguiente código es correcto:

$b = $a == 1 ? 'one' : $a == 2 ? 'two' : $a == 3 ? 'three' : 'other';

Este es interpretado como:

$b = (($a == 1 ? 'one' : $a == 2) ? 'two' : $a == 3) ? 'three' : 'other';

Y esto podría llevar a muchos errores porque podrían no ser lo que originalmente intentábamos. Así que este RFC propone depreciar y eliminar el uso de la asociación a la izquierda para operadores ternarios y forzar a los desarrolladores a usar paréntesis.

Esta es otra propuesta de dos pasos:

  • Empezando desde PHP 7.4, los ternarios alojados son uso explicito de paréntesis mostrarán una advertencia de depreciación.
  • Empezando desde PHP 8.0, habrá una compilación de errores de tiempo de uso.

Esta propuesta ha sido aprobada con 35 votos contra 10.

¿Qué Significa PHP 7.4 para los Usuarios de WordPress?

Uso de PHP (Diciembre 2019)
Uso de PHP (Diciembre 2019)

Desafortunadamente, PHP 5 sigue siendo usado por un 44.0% de todos los sitios que utilizan un lenguaje de servidor que conozcamos. Si usted agrega el número de usuarios que siguen usando PHP 7.0 y 7.1, al parecer la gran mayoría de los sitios siguen utilizando versiones de PHP que ya no son soportadas.

Versiones PHP soportadas para WordPress
Versiones soportadas de PHP (fuente de la imagen: Supported Versions)

De acuerdo a la página oficial de datos de WordPress, desde el momento en que se escribió este artículo, un sorprendente 64% de los sitios de WordPress están utilizando versiones ya no soportadas de PHP. Tan sólo un 13% están utilizando PHP 7.3. Y la última versión, PHP 7.4, ni siquiera aparece todavía. Puede ver que la gran mayoría de los usuarios, aproximadamente un 23%, siguen utilizando PHP 5.6.

WordPress Estadísticas de la versión PHP
WordPress Estadísticas de la versión PHP

Le recomendamos ampliamente preguntar a su host por una versión con soporte de PHP, de preferencia siguiendo los requisitos oficiales de WordPress. Desde el momento que se escribió este artículo, Mayo 2019, WordPress requiere:

  • Versión 7.3 de PHP o mayor.
  • Versión 5.6 de MySQL o mayor O versión 10.1 o mayor de MariaDB.
  • Soporte a HTTPS

Desempeño de PHP 7

Los números anteriores son realmente tristes, desde el punto de vista de desempeño, ya que PHP 7 es muchísimo más rápido. Aquí tenemos algunos datos:

Hicimos nuestros propios benchmarks con PHP 7.3. Y vimos que WordPress 5.0 en PHP 7.3 podía ejecutar casi el triple de transacciones (peticiones) por segundo en comparación a PHP 5.6. ¡Sacaremos benchmarks de PHP 7.4 muy pronto!

WordPress benchmarks de PHP 5.0
WordPress benchmarks de PHP 5.0
  • WordPress 5.0 benchmark de PHP 5.6: 91.64 peticiones/segundo
  • WordPress 5.0 benchmark de PHP 7.0: 206.71 peticiones/segundo
  • WordPress 5.0 benchmark de PHP 7.1: 210.98 peticiones/segundo
  • WordPress 5.0 benchmark de PHP 7.2: 229.18 peticiones/segundo
  • WordPress 5.0 benchmark de PHP 7.3: 253.20 peticiones/segundo🏆

Muchos tardan en actualizarlo simplemente por todo el tiempo que requiere hacer pruebas con todos sus plugins y temas, para asegurar que funcionen de forma apropiada. Pero en muchas ocasiones, simplemente es porque aún no lo han hecho.

Revisando Su Versión de PHP

¿No está seguro de que versión de PHP está usando? Una de las formas más sencillas para revisar es usar una herramienta como Pingdom o Google Chrome Devtools. El primer encabezado de petición HTTP típicamente mostrará su versión.

Cheque la versión PHP en Pingdom
Cheque la versión PHP en Pingdom

Esto depende de que el host no modifique el valor de encabezado X-Powered-By. Sin embargo, muchos lo hacen por razones de seguridad (incluyendo a Kinsta). Si es así, usted podría no ver su versión de PHP, en ese caso, si está utilizando WordPress 5.2 o en adelante, hay una nueva herramienta de estado del sitio. Vaya a “herramientas” -> “Site Health” -> “Info” y bajo la sección de “Servidor” usted encontrará la versión de PHP del servidor.

Revise la versión de PHP con la herramienta de Revisión de Estado de Salud de WordPress
Revise la versión de PHP con la herramienta de Revisión de Estado de Salud de WordPress

O también podría instalar un plugin gratuito como Version Info que le mostrará la información básica del servidor en el pie de página de su dashboard de administrador de WordPress. Otras formas de ver su versión de PHP incluyen el subir un archivo a través de FTP, o simplemente ponerse en contacto con su host y preguntarle.

Actualizando a PHP 7.4

La versión final de PHP 7.4 aún no ha salido. Sin embargo, puede empezar a probar la versión beta (PHP 7.4-RC4) en Kinsta ahora mismo. Alternativamente, usted podría probar su sitio de WordPress localmente o chequear sus suscripciones en un entorno como Docker, el cual le permite probar distintas versiones de PHP desde una línea de comando.

La manera más fácil de empezar a probar es crear un entorno de prueba, ya que se parecerá mucho a su sitio de producción en vivo. En el panel de control de MyKinsta, haga clic en su sitio y cambie a un entorno de prueba.

Crear un entorno de prueba de WordPress
Crear un entorno de prueba de WordPress

Luego, en el menú «Herramientas», cambie su motor PHP a PHP 7.4 (Beta). A continuación, puede empezar a realizar pruebas para garantizar la compatibilidad de su código, plugins de terceros y temas.

Al igual que las versiones anteriores de PHP, nuestra función de autocuración de PHP es totalmente compatible con PHP 7.4. Si PHP se cae por cualquier razón, lo reiniciaremos automáticamente. Si el reinicio no arregla el problema, nuestro sistema de monitoreo alertará a nuestro equipo de administradores de sistemas para que investiguen la causa del problema.

Cambiar a PHP 7.4
Cambiar a PHP 7.4

Vea los detalles sobre el lanzamiento de PHP 7.4 en Kinsta.

Instalando y Usando PHP 7.4 en Docker

Instalando Nginx Docker Image
Instalando Nginx Docker Image

Si usted prefiere utilizar su código PHP 7.4 en su navegador, también podría instalar una imagen de Nginx o Apache. Pero no se preocupe. Sólo siga las instrucciones del desarrollador. Copie y pegue los comandos desde la página de imagen de Docker a su herramienta de línea de comando y estará listo.

Resumen

En este artículo, hablamos de varios cambios y adiciones que podemos esperar del lanzamiento de PHP 7.4. Si está buscando la lista completa de funciones, junto con la documentación oficial de RFC, chequee estos siguientes recursos:

Le mantendremos actualizado con toda la información más reciente sobre PHP 7.4. Si es cliente de Kinsta, ya puede empezar a mover sus sitios de WordPress a la última versión.

¿Ya está listo para probar las próximas funciones de PHP? ¿Cuál es su favorita? Comparta con nosotros lo que usted piensa en la sección de comentarios.

Carlo Daniele Kinsta

Carlo es un diseñador y desarrollador de front-end freelance. Cuando escribe artículos y tutoriales, Carlo se ocupa principalmente de los estándares web, pero cuando juega con sitios web, su mejor compañero de trabajo es WordPress.