Novedades de PHP 8: ¡Todo lo que necesita saber!

Publicado: 2021-01-06

Nos pondremos en contacto con PHP8 el 26 de noviembre de 2020 y, ciertamente, se está escribiendo mucho sobre las próximas funciones de esta apreciada versión.

PHP 8

Como es una versión principal, habrá cambios de última hora y nuevas funciones, además de que es importante estar al tanto de todo lo que está cambiando. Hará que sea conveniente pensar en cómo PHP8 afectará sus aplicaciones y qué acciones se necesitarán tomar para garantizar que pueda actualizar convenientemente sin incidentes.

Pasamos por algunos de los cambios más importantes para descubrir qué obtendremos en la próxima versión de PHP y qué vale la pena criticar.

¡Comencemos con la descripción general!

Descripción general de PHP 8

Como se mencionó anteriormente, PHP 8 presenta un paquete de nuevas características, mejoras, funciones y obsolescencias para el lenguaje. Entre todos estos, la característica más discutida es el compilador JIT. Sin embargo, las características de mejora del rendimiento como JIT merecen el centro de atención, pero se espera que las mejoras sintácticas tengan más éxito para los practicantes de PHP, diríamos, "al menos en el corto plazo".

Una historia de cambio

Se proponen, debaten, implementan y aprueban algunos cambios de PHP en poco tiempo. Son populares, no controversiales y tienen un método natural para implementarlos.

Y después de eso vienen los que se prueban, fallan y regresan varias veces antes de que los aceptemos finalmente. Algunas veces, la implementación requiere mucho tiempo para resolverse y, a veces, la idea en sí está a medias y, a veces, la comunidad en sí aún no se ha entusiasmado con la idea: "todavía no es el momento".

Los créditos caen directamente en la categoría de tipo. Se propusieron por primera vez en el año 2016 para PHP 7.1. Sin embargo, se encontraron con una obstinada resistencia y perdieron el voto de aceptación por un amplio margen. Ahora, un avance rápido de cuatro años, y una propuesta bastante similar, aunque de alcance ligeramente reducido, surgió con un solo disidente. ¡Evidentemente es una idea cuyo momento ciertamente ha llegado!

¿Cuáles son los problemas con el código antiguo?

Como PHP 8 es una gran versión nueva, deberíamos esperar que el código antiguo ya no sea compatible. Sin embargo, la mayoría de los cambios que podrían traer complicaciones ya se incluyeron en las versiones 7.2 , 7.3 y 7.4 . Hablemos ahora de los últimos cambios. Ellos son:

Legado de citas mágicas

  • el verdadero tipo
  • filtro FILTER_SANITIZE_MAGIC_QUOTES
  • Desvincular $this de los cierres no estáticos
  • array_key_exists() con objetos
  • mb_strrpos() con codificación como tercer argumento
  • Métodos de exportación de reflexión ()
  • función convert_cyr_string()
  • mezcla de orden de parámetros implode()
  • función restaurar_incluir_ruta()
  • función hebrevc()
  • función money_format()
  • directiva allow_url_include ini
  • función ezmlm_hash()

Nuevas funciones en PHP 8

str_contiene

Si una cadena contiene otra, existen numerosas formas de averiguarlo.

Generalmente, usará strpos(). Como sabes, strpos() toma un pajar al lado de la aguja que deseas buscar. Devuelve un número entero que muestra la primera posición en la que ve la aguja.

Ahora, como está devolviendo la posición de una cadena en otra, simplemente no puede verificar si strpos() lo descubrió o no; si devuelve "0" (las posiciones están indexadas a cero y comienzan con 0 en lugar de 1), entonces el condicional lo tratará como un valor falso e indicará que no se encontró.

¿Qué significa eso?

Tendrás que escribir condicional –“strpos($pajar, $aguja) !== falso.” False indica que no pudo encontrar la posición de la cadena. ¡Este es un método no transparente y esotérico para buscar una cadena en una cadena! Bueno, no es tan confuso.

Para evitar esto, PHP 8 trae str_contains(). El trabajo de str_contains() es devolver un booleano simple que muestre si la aguja está presente o no en el pajar. Eso es mucho más fácil de escribir, además de eso, entiéndalo como alguien que mantiene el código, ¿no es así?

 if (str_contains( 'Foo Bar Baz' , 'Foo' )) { // FOUND }

PHP 8: Características y cambios del motor

Hay algunas características nuevas del motor y cambios notados en PHP 8. La característica principal, sin duda, es el nuevo compilador JIT.

Compilador JIT

  • Cumplimiento de LSP
  • Errores fatales en firmas de métodos incompatibles
  • Recurso “Clases“
  • XML-RPC ahora está en PECL
  • Comportamiento de afirmación
  • Cambios de reflexión

Por el bien del objetivo principal de este blog, nos centraremos en el compilador JIT, las "clases" de recursos y, por último, los cambios de API de reflejo.

Compilador justo a tiempo ( RFC )

Debido a las mejoras de velocidad realizadas antes del lanzamiento de PHP7, tuvo lugar el nacimiento del compilador Just-In-Time (o JIT). Se está introduciendo a PHP8 porque casi no hay más mejoras en la velocidad que se puedan lograr sin usar un JIT. La idea es que mejorará el rendimiento de PHP.

El código PHP se traduce en bytecodes cuando se ejecuta, y esos bytecodes se utilizan más para ejecutar los pasos del programa.

PHP analizará el código que ejecutaste, eso es lo que significa un JIT. Además, puede tomar decisiones en tiempo real distintas de las mejoras de rendimiento en el código a medida que lo ejecuta. Va a ser muy útil en aplicaciones intensivas de CPU y no solo mientras se usa en escenarios basados ​​en la web.

Eso refleja que las aplicaciones PHP del lado del servidor ciertamente pueden ser más frecuentes con el sistema JIT incorporado de PHP.

Primero debe activar JIT si desea usarlo. En nuestro sistema de prueba (Ubuntu 20.04), ya hemos instalado el módulo opcache de PHP, que instalamos con el paquete principal de PHP8. Lo hemos configurado en el archivo ubicado en /etc/php/8.0/cli/conf.d/10-opcache.ini.

Ahora, ya está todo listo para activar JIT, ¿verdad?  

  • Habilitar opcaché

Puede asignar almacenamiento de memoria a la configuración opcache.jit_buffer_size . Su archivo aparecerá así en mi sistema.

  1. zend_extension=opcache.so
  2. opcache.enable_cli=1
  3. ; configuración para el módulo php opcache
  4. opcache.jit_buffer_size=256M

Además, use la función opcache_get_status() para asegurarse de que esté activa. Mueva su mirada sobre la parte 'jit' de esta matriz y obtenga información sobre el estado actual de JIT.


var_dump(opcache_get_status()['jit']);

Si JIT se ha activado perfectamente, esto debería imprimirse como se muestra allí.

  1. matriz (7) {
  2. [“habilitado”]=>
  3. booleano (verdadero)
  4. [“encendido”]=>
  5. booleano (verdadero)
  6. [“amable”]=>
  7. int(5)
  8. [“nivel_opción”]=>
  9. int(4)
  10. [“opt_flags”]=>
  11. int(6)
  12. [“tamaño_búfer”]=>
  13. int(268435440)
  14. [“buffer_free”]=>
  15. int(268432880)
  16. }

Entonces, ¿fue más rápido? En una palabra, exclamaríamos un cálido “sí”.

Nos hemos dado cuenta de que algunas personas realizan pruebas comparativas con la ayuda de un conjunto de Mandelbrot, por lo que decidimos usar una biblioteca que creamos hace un tiempo que dibuja diferentes tipos de fractales en PHP. Todo lo que hicimos fue generar tres fractales y rastrear cuánto tiempo llevó utilizar la función de microtomo(). Hemos mostrado los resultados para PHP 7.4.8 a continuación.

  • Barco en llamas – 84.20269203186
  • Mandlebrot – 21.552599906921
  • Tricornio – 32.685042858124

Cuando ejecutamos el mismo código en PHP8, fue bastante más rápido. Los números hablarán por sí solos. .

  • Barco en llamas – 15.272277116776
  • Mandlebrot -3.7528541088104
  • Tricornio -4.4957919120789

Este enorme aumento de velocidad es bastante interesante. El código que usamos aquí crea fractales de gran tamaño, pero recordamos que al crear el código pasamos la mayor parte de nuestro tiempo esperando la generación de fractales.

Esta adición es interesante para nosotros ya que hemos llevado PHP a sus límites en algunas ocasiones (fuera de la generación de fractales). Podemos notar que esto es de gran beneficio para el futuro de PHP y permitirá que se elija el idioma para situaciones fuera del idioma normal del sitio web.

No hemos mirado el incremento de velocidad para aplicaciones como WordPress o Drupal, pero por lo que hemos leído, ciertamente hay poca diferencia en ese tipo de aplicaciones. En el futuro, ejecutaremos puntos de referencia en estas plataformas para descubrir qué tipo de diferencia marca el JIT allí.

Tipos de unión ( RFC )

Desde PHP7, ha sido posible estipular qué tipo de valores de retorno y tipos de argumentos. Esto permitirá que PHP arroje un error en caso de que el tipo de argumento que está pasando no sea idéntico al tipo esperado. Es crucial asegurarse de que las funciones reciban y produzcan los tipos perfectos de valor en un lenguaje poco tipificado como PHP.

En PHP8, ahora es posible estipular varios tipos de argumentos y valores de retorno, divididos por un carácter de canalización.

A continuación mostramos una función que es capaz de aceptar un valor flotante o entero.

 function addNumbers(int|float $number1, int|float $number2) : int|float { return $number1 + $number2; }

Anteriormente, era necesario generar una función idéntica a esta sin ninguna sugerencia de tipo porque PHP podía mostrar silenciosamente el tipo en caso de que el argumento pasado no fuera correcto. Significaba que en caso de que establezcamos el tipo de argumento como un número entero, PHP mostraría cualquier valor flotante en un número entero. Sin duda, puede conducir a algunos errores difíciles de detectar en caso de que no esté realizando pruebas unitarias.

Simplemente lo llamamos como cualquier otro para usar la función anterior

 echo addNumbers(1, 1); // prints 2 echo addNumbers(1.1, 1.1); // prints 2.2

En caso de que intentemos pasar una cadena a la función idéntica:

 echo addNumbers('one', 'two');

Recibiremos un error fatal de PHP exclamando que necesitamos pasar un flotante o un "int" a la función.

No puede usar el tipo void como un tipo de unión porque estipula que la función no devolverá nada. En palabras simples, no puede exclamar que una función va a devolver un vacío o un número entero; recibirá un error fatal de PHP.

Si bien podemos ver un cambio normal, esta función se usó un poco, ya que antes solo era posible estipular varios tipos de valores en los comentarios, lo que resultó en que los comentarios del bloque de documentos se volvieran más detallados que el código.

El Operador Nullsafe (RFC)

Además del operador coalescente nulo, la capacidad de detectar valores de retorno nulos es posible directamente desde los métodos. Si no lo sabía, el operador de fusión nulo le permite obtener un valor y no tiene que probar si el valor está presente, además de devolver un valor diferente en caso de que el primer valor sea nulo.

Entonces, podemos hacer esto para obtener un valor de: "$_GET superglobal". y en caso de que ese valor no esté presente, entonces “0”.


1. $page = $_GET['page'] ?? 0;

2. echo $pagina;

El funcionamiento del operador seguro nulo es el mismo, pero le permite crear un atajo útil y probar un retorno nulo de una forma antes de intentar usar ese valor.

Nos dimos cuenta de que esto será útil en última instancia en Drupal, donde tendemos a escribir gran parte del código de verificación para garantizar que los "retornos de los métodos" o las "propiedades de los objetos" tengan cosas en ellos antes de utilizarlos. Esto es obligatorio por el estado contextual de los objetos en Drupal por el contenido que contienen. Este cambio seguramente simplificará algunas de las comprobaciones.

Argumentos con nombre ( RFC )

Los argumentos con nombre le permiten estipular un orden diferente de argumentos y funciones de llamada. Tome la siguiente función normal que tiene dos parámetros. Llena una matriz a la longitud dada.

 function fillArray(array $arrayToFill, int $number) : array { for ($i = 0 $i < $number; ++$i) { $arrayToFill[$i] =1; } return $arrayToFill; }

Podemos pasar los argumentos en el arreglo en el que están definidos podemos llamar a esta técnica de la manera normal.

 $newArray = fillArray([], 2);

A partir de PHP8, ahora puede nombrar los parámetros a medida que los pasa a la función. También permite enviar los parámetros en el orden que queramos.

 $newArray = fillArray(number: 2, arrayToFill: []);

Un ejemplo normal, pero también puede hacer que el código sea más legible.

Esta técnica funciona con todas las funciones de PHP, no solo con las definidas por el usuario. En el lenguaje PHP, las funciones de matriz y cadena tienen órdenes de parámetros no idénticos. Por lo tanto, es una adición verdaderamente bienvenida.

Atributos V2 ( RFC1 RFC2 RFC3 )

Los atributos proporcionan un mecanismo para adjuntar metadatos a clases, funciones, propiedades de clase, parámetros de función y constantes de PHP. No se puede acceder directamente a ellos a través del código, y debe extraerlos con la ayuda de las clases de reflexión incorporadas de PHP.

La clase ReflectionClass ha estado en PHP desde PHP5; sin embargo, el método getAttribute() es nuevo para PHP8. Este método devuelve un rango de objetos ReflectionAttribute que incluirán información sobre los atributos.

Esta adición enfrentó algunos cambios (como podemos notar en los múltiples RFC anteriores). En caso de que cree una instancia de la clase, puede usar ReflectionClass e imprimir la información del atributo contenida en un nivel de clase. Hay muchos atributos en PHP8, por lo que recomendamos leer los RFC y familiarizarse con lo que realmente son y cómo puede integrarlos en su código.

Expresión de coincidencia ( RFC )

En PHP 8, podemos comparar la nueva expresión de coincidencia con una declaración de cambio abreviada.

Parece un poco como una declaración de función que devolverá un valor en función del valor pasado.

La declaración de cambio en PHP es sorprendente cuando desea verificar la condición en la expresión idéntica sin incluir varias declaraciones if en total.

Aquí traemos una comparación básica if-else en una expresión idéntica.

 <?php if ($i == 'apple') { echo 'i is apple'; } elseif ($i == 'cake') { echo 'i is cake'; } else { echo 'i is pizza'; }

Y así es como aparecería la declaración de switch equivalente de nuestro ejemplo anterior

 <?php switch ($i) { case 'apple': echo 'i is apple'; break; case 'cake': echo 'i is cake'; break; default: echo 'i is pizza'; }

Recursos “Clases”

Las “clases” de recursos vienen en la lista de cambios importantes en PHP 8 y ​​sirven como reemplazos no instanciables para tipos de recursos dados. Consulte a continuación para conocer los reemplazos disponibles que incluyen:

  • CurlHandle — curl_init() ahora devuelve CurlHandle, relacionando un recurso curl.
  • Socket / AddressInfo — Dado por la extensión de sockets; la cantidad de funciones socket_*() devuelve un Socket, mientras que la función socket_address_info_lookup() devuelve una instancia de AddressInfo.
  • GdImage : representa un recurso GD, tal como lo restauran las numerosas funciones imagecreatefrom*().

Además, es fundamental tener en cuenta que los recursos no se destruyen con funciones como curl_close(). Más bien, debe desarmar () la instancia para eliminar la referencia, ya que ahora es una instancia de clase.
Obtiene la capacidad de especificar las clases como sugerencias de tipo en sus funciones y métodos.
Anteriormente, teníamos que devolver valores sin escribir o dejar argumentos de recursos y documentarlos a través de anotaciones, pero ahora puede tener tipos explícitos, y eso no solo hace que su código sea más legible, sino también más seguro.
¿Cuál es la compensación aquí?
Ahora deberá actualizar su código si desea destruir recursos con la ayuda de unset() en lugar de las funciones anteriores utilizadas para destruir recursos. Esto normalmente se puede lograr a través de buscar y reemplazar.

Cambios en la API de reflexión

Otro pequeño, pero un cambio vital en PHP 8 está relacionado con Reflection API. Mientras usa el sistema de atributos, puede recuperar convenientemente esos atributos a través de la API de Reflection en cualquier clase de reflexión.
Con la adición de tipos mixtos y de unión, las técnicas de ReflectionParameter getClass(), isCallable() e isArray() ahora están obsoletas.
El escenario es así porque usar getType() es mucho mejor y obtienes la lista completa de tipos que satisface un parámetro específico.

Mejoras en la sintaxis de PHP 8

Como estamos notando, JIT se está robando los titulares; Las mejoras sintácticas de PHP 8 brindan enormes ventajas de calidad de vida para los desarrolladores de PHP.
No importa si se trata de eliminar el repetitivo común entre los argumentos de constructor promocionados o el manejo mejorado de excepciones y errores, hay mucho por lo que los desarrolladores deben sentirse entusiasmados.

  • pseudotipo “mixto”
  • Tipos de Unión
  • Promoción inmobiliaria Class Constructor
  • Lanzar excepciones de expresiones
  • Atributos
  • ::clase ubicuidad
  • Captura solo por tipo
  • Expresiones de coincidencia

Para el mantenimiento de este blog, nos estamos enfocando en los tipos de unión, los atributos y las expresiones de coincidencia.

Tipos de unión

Los tipos de unión muestran que un valor es uno entre dos o más tipos especificados. Se hace con una barra vertical colocada entre cada tipo permitido. Para varios desarrolladores que profundizan en las anotaciones de PHP para devolver valores o especificar sus parámetros, lo más probable es que ya haya estado haciendo esto.
Los tipos de unión pueden traer mucha complejidad y dificultad de comprensión para aquellos que aceptan muchos tipos diferentes o devuelven muchos tipos diferentes.
Aún así, esto te será muy útil en varias ocasiones. Por ejemplo, en caso de que pueda aceptar un objeto que implemente la nueva interfaz Stringable ("string|Stringable"), o una cadena, o si puede aceptar un objeto que implemente la interfaz Traversable ("array|Traversable") o una matriz .

Expresiones de coincidencia

Las expresiones de coincidencia cortan las conjeturas relacionadas con determinar si la falla al romper dentro de un caso de interruptor dado es intencional o no. También simplifica el patrón normal de asignación de un valor sobre la base de una coincidencia.
Cuando se usa, el valor que le pasamos a match() se comparará directamente con la expresión que se encuentre en el lado izquierdo. No importa que sea una expresión o un valor, el valor que pase a match() debe coincidir con él para que sea elegido.
Cuando se compara, se estima la expresión presente a la derecha y se devuelve su valor de retorno, mientras que las expresiones solo pueden ser funciones Lambda o invocables, y no se permiten cierres de varias líneas.

Atributos

PHP 8 también integra atributos a nivel de idioma. Si bien los atributos están presentes desde hace más de 15 años a través de anotaciones docblock, integrarlos en el lenguaje ofrece un mejor rendimiento y, sin duda, más potencia y más coherencia. Es probable que veamos atributos muy utilizados en el desarrollo de herramientas y aplicaciones rápidas.

Conclusión

Ciertamente, hay algunos cambios en PHP8. Aún así, parece que la mayoría del código obsoleto que se elimina es para funciones más antiguas que no hemos visto que se usen en los últimos tiempos.
Estamos bastante interesados ​​en notar qué impacto tendrá el motor JIT en las bases de código que usamos y también en la comunidad PHP más amplia, por lo que recomendamos escanear su base de código en busca de incompatibilidades con PHP8 y ejecutar pruebas unitarias para garantizar que su PHP las aplicaciones funcionan perfectamente antes de decir “sí” a la actualización.