PHP 8 y sus características: Un vistazo en profundidad

PHP 8 es una actualización importante del lenguaje PHP que ha introducido muchas nuevas características y optimizaciones. Desde argumentos con nombre y tipos de unión hasta la compilación JIT, PHP 8 ha mejorado significativamente la eficiencia y la legibilidad del código. En este artículo, vamos a explorar en profundidad estas características y cómo pueden beneficiar a los desarrolladores de PHP.

Union Types

Los tipos de unión son una característica muy esperada que se ha incorporado en PHP 8. Esta característica permite a los desarrolladores declarar que un parámetro de función, una propiedad de clase o un valor de retorno puede ser de varios tipos diferentes. En otras palabras, los tipos de unión permiten combinar tipos de datos en una declaración de tipo.

Antes de PHP 8, los desarrolladores tenían que recurrir a docblocks o a la anotación de tipo mixed para indicar que una variable podría contener diferentes tipos de datos. Sin embargo, estas soluciones no eran ideales, ya que no proporcionaban ninguna garantía en tiempo de ejecución y no eran muy explícitas.

Con los tipos de unión, puedes declarar explícitamente los tipos de datos permitidos en tu código, lo que puede ayudar a prevenir errores y hacer que tu código sea más fácil de entender. Aquí tienes un ejemplo de cómo puedes usar los tipos de unión en una declaración de función:

function setID(int|string $id): void {
    $this->id = $id;
}

En este ejemplo, la función setID puede aceptar tanto un entero como una cadena como su parámetro $id. Esto significa que puedes llamar a la función con un número o una cadena sin que se produzca un error de tipo.

Además, los tipos de unión pueden ser nulos utilizando |null o la notación existente ?. Esto puede ser útil cuando trabajas con funciones que pueden devolver un valor o null. Aquí tienes un ejemplo:

function findUser(int $id): User|null {
    // ...
}

En este ejemplo, la función findUser puede devolver una instancia de la clase User o null, dependiendo de si se encuentra un usuario con el ID proporcionado.

Los tipos de unión son una adición poderosa a PHP que puede ayudarte a escribir código más seguro y más claro. Sin embargo, como con cualquier característica, es importante usarlos con moderación y tener en cuenta que pueden hacer que tu código sea más difícil de entender si se usan en exceso.

Match Expressions

Los argumentos con nombre son una de las características más destacadas de PHP 8. Esta característica permite pasar valores a una función basándose en el nombre del parámetro en lugar de su posición en la lista de argumentos. Esto puede hacer que el código sea más legible y autoexplicativo, y también permite omitir argumentos opcionales.

Antes de PHP 8, los argumentos se pasaban a las funciones en un orden específico. Si una función tenía varios argumentos, y especialmente si algunos de ellos eran opcionales, podía ser difícil recordar el orden correcto, y omitir un argumento opcional en medio de la lista podía ser complicado.

Con los argumentos con nombre, puedes especificar directamente los valores de los argumentos que quieres pasar, sin importar su orden. Además, puedes omitir argumentos opcionales sin tener que especificar todos los argumentos que vienen antes de ellos en la lista.

Aquí tienes un ejemplo de cómo se pueden utilizar los argumentos con nombre en PHP 8:

function foo(string $a, string $b, ?string $c = null, ?string $d = null) 
{ /* … */ }

foo(
 b: 'value b', 
 a: 'value a', 
 d: 'value d',
);

En este ejemplo, estamos llamando a la función foo y pasando valores a los argumentos $a, $b, y $d. Notarás que no estamos pasando un valor para el argumento $c, y eso está perfectamente bien porque $c es un argumento opcional.

Los argumentos con nombre pueden hacer que el código sea más fácil de leer y entender, ya que no tienes que recordar el orden de los argumentos, y es claro qué valor se está pasando a qué argumento. También pueden hacer que sea más fácil trabajar con funciones que tienen muchos argumentos, especialmente si algunos de ellos son opcionales.

Es importante tener en cuenta que los argumentos con nombre son una característica de sintaxis, y no cambian la forma en que PHP pasa argumentos a las funciones. Los argumentos en PHP todavía se pasan por valor (o por referencia, si se especifica), y los argumentos con nombre no cambian eso.

En resumen, los argumentos con nombre son una adición potente y flexible a PHP 8 que puede mejorar la legibilidad y la mantenibilidad del código.

Constructor Property Promotion

La promoción de propiedades del constructor es una característica que reduce significativamente la cantidad de código que necesitamos escribir para objetos simples. Esta característica es especialmente útil cuando trabajamos con objetos de transferencia de datos (DTOs) y objetos de valor (VOs).

En lugar de declarar propiedades de clase y luego inicializarlas en el constructor, PHP 8 nos permite hacer ambas cosas al mismo tiempo en la definición del constructor. Aquí tienes un ejemplo de cómo se ve:

class CustomerDTO
{
 public function __construct(
 public string $name, 
 public string $email, 
 public DateTimeImmutable $birth_date,
 ) {}
}

En este ejemplo, $name, $email y $birth_date son automáticamente declarados como propiedades públicas y asignados los valores que se pasan al constructor. Esto es equivalente al siguiente código en versiones anteriores de PHP:

class CustomerDTO
{
 public string $name;
 public string $email;
 public DateTimeImmutable $birth_date;

 public function __construct(
 string $name, 
 string $email, 
 DateTimeImmutable $birth_date
 ) {
  $this->name = $name;
  $this->email = $email;
  $this->birth_date = $birth_date;
 }
}

Como puedes ver, la promoción de propiedades del constructor nos permite ahorrar bastante código y hace que nuestro código sea más limpio y fácil de leer.

Es importante mencionar que las propiedades promovidas pueden ser de cualquier visibilidad: public, protected o private. Además, también pueden tener valores predeterminados. Sin embargo, no se permiten expresiones como new ... para valores predeterminados.

Además, las propiedades promovidas pueden tener atributos y comentarios de documentación, y estos pueden ser accedidos a través de la reflexión.

La promoción de propiedades del constructor es una característica potente en PHP 8 que puede hacer que nuestro código sea más limpio y conciso. Sin embargo, como con cualquier característica, es importante usarla con cuidado y entender completamente cómo funciona antes de empezar a usarla en el código de producción.

JIT Compilation

El compilador JIT (Just In Time) es una de las características más destacadas de PHP 8. JIT, que significa «Just In Time», es un término que se utiliza para describir una técnica de compilación que se realiza durante la ejecución de un programa, en lugar de antes de la ejecución. Esta característica tiene el potencial de mejorar significativamente el rendimiento de las aplicaciones PHP, especialmente las que son intensivas en cálculos.

El compilador JIT en PHP 8 es una mejora significativa sobre el motor Zend que se utilizaba en versiones anteriores de PHP. El motor Zend también compilaba el código PHP en un código de bytes intermedio, pero luego lo interpretaba, en lugar de compilarlo en código de máquina. El compilador JIT, por otro lado, compila este código de bytes intermedio en código de máquina nativo, que puede ser ejecutado directamente por la CPU. Esto elimina la necesidad de interpretar el código de bytes, lo que puede resultar en mejoras de rendimiento.

Aquí hay un ejemplo de cómo se puede habilitar el compilador JIT en PHP 8:

[jit]
; Enable or disable JIT compilation.
; Possible values are "disable", "tracing", "function" and "on".
; "tracing" and "function" are experimental and for testing only.
; When "on", the JIT strategy is determined by the opcache.jit setting.
opcache.jit=tracing

; The opcache.jit_buffer_size setting determines the size of the memory
; buffer that is used by the JIT compiler for storing the compiled code.
; If set to 0, JIT compilation is effectively disabled.
opcache.jit_buffer_size=50M

; The opcache.jit setting determines the strategy used by the JIT compiler.
; Possible values are "disable", "tracing", "function" and "on".
; "tracing" and "function" are experimental and for testing only.
; When "on", the JIT strategy is determined by the opcache.jit setting.
opcache.jit=tracing

Es importante tener en cuenta que, aunque el compilador JIT puede mejorar el rendimiento de las aplicaciones PHP, no todas las aplicaciones se beneficiarán de él. Las aplicaciones que son intensivas en E/S o en red, por ejemplo, es probable que no vean mejoras significativas de rendimiento con el JIT. Sin embargo, las aplicaciones que son intensivas en cálculos, como las que realizan tareas de procesamiento de imágenes o de aprendizaje automático, pueden ver mejoras de rendimiento significativas.

Además, el compilador JIT es una característica relativamente nueva en PHP, y todavía está en desarrollo. Por lo tanto, es posible que encuentres problemas o comportamientos inesperados al usarlo. Te recomendamos que pruebes a fondo tu aplicación con el JIT habilitado en un entorno de desarrollo antes de considerar su uso en producción.

Nullsafe Operator

El operador Nullsafe es una adición a PHP 8 que permite llamar a métodos y propiedades de manera segura en objetos que podrían ser nulos. Antes de PHP 8, si intentabas llamar a un método en un objeto que podría ser nulo, PHP lanzaría un error. Con el operador Nullsafe, PHP en su lugar devolverá nulo.

Por ejemplo, si tienes una cadena de llamadas a métodos donde cada método puede devolver nulo, tendrías que hacer comprobaciones intermedias para evitar errores:

$country = null;

if ($session !== null) {
 $user = $session->user;

 if ($user !== null) {
  $address = $user->getAddress();

  if ($address !== null) {
   $country = $address->country;
  }
 }
}

Con el operador Nullsafe, puedes simplificar el código anterior a:

$country = $session?->user?->getAddress()?->country;

El operador Nullsafe utiliza una forma de «cortocircuito»: al escribir ?->, PHP mira lo que está a la izquierda de este operador, si es nulo, entonces lo que está a la derecha simplemente se descarta. Esto significa que si tienes una función costosa en la cadena de llamadas, esa función solo se ejecutará si todos los métodos anteriores devuelven un objeto no nulo:

$foo?->bar(expensive_function());

En este caso, expensive_function() solo se ejecutará si $foo no es nulo.

Es importante tener en cuenta que el operador Nullsafe solo se puede usar para leer datos. No puedes usarlo para escribir datos en objetos. Por ejemplo, el siguiente código dará un error:

$offer?->invoice?->date = new DateTime();

El operador Nullsafe es definitivamente una pieza que faltaba en el rompecabezas de PHP. Dada su naturaleza dinámica, es bueno tener una forma suave de lidiar con nulos. La diferencia y la superposición entre el operador Nullsafe y el operador de coalescencia nula pueden parecer un poco confusas al principio, pero estoy seguro de que nos acostumbraremos a ellas.

Otras características y mejoras

Además de las características ya mencionadas, PHP 8 ha introducido una serie de otras mejoras y cambios que vale la pena mencionar.

Mejoras en el sistema de tipos y manejo de errores

PHP 8 ha introducido mejoras en el sistema de tipos y el manejo de errores. Ahora, la mayoría de las funciones internas lanzan una excepción de Error si la validación de los parámetros falla. Esto hace que el manejo de errores sea más consistente y predecible.

strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given
array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0

Mejoras en la sintaxis

PHP 8 también ha introducido varias mejoras en la sintaxis. Por ejemplo, ahora se permite una coma final en las listas de parámetros y en las listas de uso de cierres. Además, el operador @ ya no silencia los errores fatales.

function foo(string $a, string $b, ?string $c = null, ?string $d = null,) 
{ /* … */ }

$foo = function($a, $b,) use ($c, $d,) { /* … */ };

Nuevas clases, interfaces y funciones

PHP 8 ha introducido varias nuevas clases, interfaces y funciones. Por ejemplo, se ha añadido la clase Weak Map, la interfaz Stringable y funciones como str_contains(), str_starts_with(), str_ends_with(), fdiv(), get_debug_type(), get_resource_id() y token_get_all().

$map = new WeakMap();
$obj = new stdClass;
$map[$obj] = 42;

echo isset($map[$obj]); // true

unset($obj);

echo isset($map[$obj]); // false

echo str_contains('hello world', 'world'); // true
echo str_starts_with('hello world', 'hello'); // true
echo str_ends_with('hello world', 'world'); // true

echo fdiv(10, 0); // INF
echo fdiv(-10, 0); // -INF
echo fdiv(0, 0); // NAN

echo get_debug_type(new stdClass); // "stdClass"
echo get_debug_type([1, 2, 3]); // "array"
echo get_debug_type(42); // "integer"
echo get_debug_type(null); // "null"

$resource = fopen('php://memory', 'r');
echo get_resource_id($resource); // e.g. "2"

$tokens = token_get_all('<?php echo "Hello, world!";');
print_r($tokens);

Estas son solo algunas de las muchas mejoras y características nuevas que PHP 8 ha introducido. Para obtener una descripción completa de todas las nuevas características y cambios, te recomiendo que consultes la documentación oficial de PHP 8.

Conclusión

PHP 8 es un gran paso adelante para el lenguaje PHP. Con la introducción de características como los tipos de unión, argumentos con nombre, expresiones match, promoción de propiedades constructivas, operador nullsafe y compilación JIT, PHP 8 ha mejorado significativamente tanto en términos de rendimiento como de legibilidad del código.

Los tipos de unión y los argumentos con nombre son particularmente útiles para mejorar la legibilidad y la robustez del código. Los tipos de unión permiten especificar que un parámetro o valor de retorno puede ser de varios tipos, lo que puede ayudar a evitar errores y hacer que el código sea más fácil de entender. Los argumentos con nombre permiten pasar valores a una función basándose en el nombre del parámetro en lugar de su posición, lo que puede hacer que el código sea más fácil de leer y entender.

Las expresiones match y la promoción de propiedades constructivas son otras dos características que pueden simplificar el código y hacerlo más eficiente. Las expresiones match son una versión más potente y segura de las declaraciones switch que hemos estado usando en versiones anteriores de PHP. La promoción de propiedades constructivas permite definir y inicializar propiedades de clase en un solo lugar, lo que puede reducir la cantidad de código necesario.

El operador nullsafe es otra adición útil que puede ayudar a evitar errores comunes al tratar con valores nulos. Y finalmente, la compilación JIT promete mejoras significativas de rendimiento, aunque su impacto en las aplicaciones web de la vida real puede variar.

En resumen, PHP 8 ofrece una serie de mejoras y características nuevas que pueden ayudar a los desarrolladores a escribir código más eficiente, legible y robusto. Si aún no has tenido la oportunidad de explorar estas nuevas características, te animo a que lo hagas. Te sorprenderá la cantidad de mejoras y adiciones que se han hecho en esta última versión del lenguaje PHP.

Deja una respuesta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.