Explora las novedades de PHP 8.1: recursos y mejoras

Explora las novedades de PHP 8.1: recursos y mejoras

El PHP (Hypertext Preprocessor) fue lanzado por primera vez en junio de 1995 por Rasmus Lerdorf. En septiembre de 2023 se cumplieron 28 años desde el lanzamiento oficial de PHP. Esta versión inicial fue muy utilizada para crear páginas web dinámicas.

Dado que es un lenguaje de código abierto, desde entonces se han puesto a disposición muchas versiones y lanzamientos nuevos con la contribución de desarrolladores de todo el mundo.

La comunidad de desarrolladores que mantiene PHP en constante evolución anunció, el 25 de noviembre de 2021, la tan esperada versión de PHP 8.1.

En esta nueva versión se han añadido nuevas características y mejoras, que serán presentadas y detalladas a lo largo de este artículo.

Quienes están al día con las últimas versiones saben que la versión 8.2 fue lanzada el 8 de diciembre de 2022 (y la versión 8.3 se encuentra actualmente en fase de prueba). Próximamente haré un artículo específico para la versión 8.2.

Espero que este artículo le ayude a mantenerse actualizado con las nuevas funciones y mejoras de PHP 8.1.

Que tengas una buena lectura.


Nuevos recursos

Tipo Enum

Sin duda, este nuevo tipo de variable era una de las novedades más esperadas por los desarrolladores.

La funcionalidad Enum se introdujo en PHP 8.1 como una forma de definir y trabajar con enumeradores, que son una estructura de datos especial capaz de representar un conjunto fijo de valores con nombre. Los enumeradores son muy útiles cuando necesitas crear un conjunto limitado de opciones que pueden usarse en tu código.

Este nuevo tipo es de gran importancia ya que hace que el código fuente sea más legible y fácil de mantener.

Sintaxis del nuevo tipo Enum

En versiones anteriores a PHP 8.1, para trabajar con la estructura similar a Enums, era necesario crear una clase de la siguiente manera:

class Status
{
    const DRAFT     = 'draft';
    const PUBLISHED = 'published';
    const ARCHIVED  = 'archived';
}
function acceptStatus(string $status) {...}


Con la clase anterior definimos tres posibles estados para una entrada de blog, por ejemplo.

Para hacer lo mismo y definir una enumeración PHP 8.1, necesita el siguiente fragmento de código:

enum Status
{
    case Draft;
    case Published;
    case Archived;
}
function acceptStatus(Status $status) {...}


El código se vuelve más pequeño y más fácil de mantener, además de hacerlo más sencillo.

Usar esta enumeración es fácil, puedes incluirla como tipo en un atributo de otra clase:

class Post
{

    public Status $status;

    public function __construct(Status $status) {
        $this->status = $status;
    }

    public function getStatus(): Status {
        return $this->status;
    }
}

Esta es una característica que hace que la estructura del código fuente sea más fácil de mantener y comprender.

Read-only properties

Esta es una adición importante al lenguaje que le permite establecer propiedades de clase en solo lectura.

Esto significa que una vez que a una propiedad de solo lectura se le asigna un valor en el constructor de la clase, ya no se puede modificar ni asignar en ningún otro lugar del código de la clase.

Esto promueve la inmutabilidad y ayuda a garantizar la integridad de los datos entre objetos.

A continuación se muestra un ejemplo de cómo puedes utilizar esta nueva funcionalidad:

class Person {
    public readonly string $name;
    public readonly int $age;

    public function __construct(string $name, int $age) {
        $this->name = $name;
        $this->age = $age;
    }
}


De esta manera, al crear una instancia de un objeto pasando el nombre y la edad, ya no será posible, en tiempo de ejecución, cambiar estas dos propiedades, lo que aporta más integridad al código.

Puede ser más fácil entender esta nueva funcionalidad cuando tenemos una clase con parámetros del sistema que no deben cambiarse en ninguna situación, por ejemplo, URL de API, ID de API, etc.

Es una gran característica que aporta más seguridad al código fuente.

Sintaxis First-class Callable

La "sintaxis invocable de primera clase" es una nueva característica introducida en la nueva versión que hace que sea más fácil y legible tratar funciones y métodos como valores invocables (callable) en su código.

Esto es útil en situaciones en las que desea pasar funciones como argumentos a otras funciones, almacenar funciones en variables o devolver funciones de otras funciones.

Pasando funciones como argumentos

Antes de PHP 8.1, para pasar una función como argumento, tenías que pasar el nombre de la función como argumento string.

Ahora, puedes usar una sintaxis invocable de primera clase para hacer esto más legible:

function process(callable $func, $data) {
    return $func($data);
}

// Uso
$resultado = process(fn($x) => $x * 2, 5);
echo $resultado; // Saída: 10


Almacenando funciones en variables

Ahora puedes almacenar funciones en variables directamente usando una sintaxis invocable de primera clase:

$double = fn($x) => $x * 2;
echo $double(4); // Saída: 8


Retornando funciones de otras funciones

También puede devolver funciones de otras funciones:

function multiplier($factor) {
    return fn($x) => $x * $factor;
}

$double = multiplier(2);
echo $double(5); // Saída: 10


La función multiplier devuelve una función que multiplica su argumento por el factor dado.

La sintaxis invocable de primera clase hace que el código sea más limpio y legible cuando se trabaja con funciones como valores, lo que hace que la manipulación de funciones y métodos sea más fácil y concisa en PHP 8.1 y posteriores.

New in initializers

La funcionalidad New in initializers se introdujo en la nueva versión como una nueva característica que permite la creación de objetos directamente en el contexto de la inicialización de propiedades de clase.

Antes de PHP 8.1, era necesario crear objetos en un constructor de clases o en algún método.

Antes de PHP 8.1:

class Pessoa {
    private $nome;
    private $idade;

    public function __construct($nome, $idade) {
        $this->nome = $nome;
        $this->idade = $idade;
    }
}


Ahora, con PHP 8.1 puedes hacer lo siguiente:

class Pessoa {
    private $nome = 'John';
    private $idade = 30;
}


Esto es conveniente cuando deseas proporcionar valores iniciales o predeterminados para las propiedades de tu clase.

Esta funcionalidad no se limita solo a tipos escalares, sino que también se puede utilizar para crear objetos de clase personalizados:

class Carro {
    private $modelo = new ModeloCarro();
    private $anoFabricacao = new Ano();
}


Es importante tener en cuenta que no puedes realizar lógica o cálculos complejos mientras inicializas propiedades de esta manera.

La creación de objetos está restringida a una simple inicialización.

Pure Intersection Types

Esta es una característica interesante que permite que una variable en un método se pase como una variable iteradora y tenga un cierto tipo de datos dentro del array.

Por ejemplo, digamos que necesita iterar y realizar un recuento:

Antes de PHP 8.1 sería algo así:

function count_and_iterate(Iterator $value) {
    if (!($value instanceof Countable)) {
        throw new TypeError('value must be Countable');
    }

    foreach ($value as $val) {
        echo $val;
    }

    count($value);
}


Con la nueva funcionalidad pure intersection types:

function count_and_iterate(Iterator&Countable $value) {
    foreach ($value as $val) {
        echo $val;
    }

    count($value);
}


Aquí defines en el parámetro que la variable debe ser un Iterator con contenido de tipo Countable.

Never return type

Este es un nuevo tipo de retorno de método que le dice al compilador que el método no devolverá nada después de la ejecución:

function redirect(string $uri): never {
    header('Location: ' . $uri);
    exit();
}

function redirectToLoginPage(): never {
    redirect('/login');
    echo 'Hello'; // <- código morto detectado por análise estática
}


Una función o método declarado con tipo nunca indica que no devolverá un valor y arrojará una excepción o finalizará la ejecución del script con una llamada die(), exit(), trigger_error() o algo semejante.

Final class constants

Ahora es posible declarar constantes como finales en la clase principal, por lo que no será posible cambiarlas desde la clase secundaria.

class Foo
{
    final public const XX = "foo";
}

class Bar extends Foo
{
    public const XX = "bar"; // Fatal error
}


Esta funcionalidad aporta más seguridad al código.

Fibers

Fibers soportan la concurrencia a nivel del lenguaje.

Esta funcionalidad le permite crear 'fibras' ligeras en tu código PHP.

Las fibras se ejecutan simultáneamente, pero la ejecución entre ellas es cooperativa, lo que significa que las fibras deben ceder voluntariamente el control a otras fibras en puntos específicos del código.

<?php

function taskA(Fiber $fiberB): Fiber {
    for ($i = 1; $i <= 5; $i++) {
        echo "Tarefa A - Iteração $i\n";
        Fiber::yield(); // Pausa a execução da Tarefa A e permite que a Tarefa B seja retomada
    }
    return $fiberB;
}

function taskB(): void {
    for ($i = 1; $i <= 5; $i++) {
        echo "Tarefa B - Iteração $i\n";
        Fiber::yield(); // Pausa a execução da Tarefa B e permite que a Tarefa A seja retomada
    }
}

$fiberA = new Fiber('taskA');
$fiberB = new Fiber('taskB');

while ($fiberA->isRunning() || $fiberB->isRunning()) {
    if ($fiberA->isRunning()) {
        $fiberA->resume($fiberB); // Retoma a Tarefa A e passa o controle para a Tarefa B
    }
   
    if ($fiberB->isRunning()) {
        $fiberB->resume(); // Retoma a Tarefa B
    }
}

echo "Concluído.\n";



En el código anterior, puede ver que, usando la clase Fiber, podemos crear instancias de dos subprocesos pasando el nombre de la función a ejecutar y, así, usar los ayudantes de la clase Fiber para manipular y orquestar su ejecución.

Esta es una buena forma de ejecutar tareas concurrentes que, en cierto punto, tienen dependencias.

Array unpacking support for string-keyed arrays

Similar al operador rest de JavaScript, tenemos el operador '...' para realizar el unpacking de un array que posea sus llaves de tipo string (apenas para este caso).

$arrayA = ['a' => 1];
$arrayB = ['b' => 2];

$result = ['a' => 0, ...$arrayA, ...$arrayB];

// ['a' => 1, 'b' => 2]


En la versión anterior, era necessário utilizar el array_merge, pero en esta nueva versión, se añadió el soporte para arrays con llaves de tipo string.

Depreciaciones y remociones

A continuación, se enumeran algunas de las características obsoletas y eliminadas en PHP 8.1:

  1. Pasar null para parámetros de funciones internas no anulables quedó obsoleto.
  2. Tipos de retorno tentativos en métodos internos de clase PHP.
  3. La interfaz serializable está obsoleta.
  4. Funciones de en/decode de entidades HTML procesan comillas simples y las sustituyen por defecto.
  5. Restricciones en la variable $GLOBALS.
  6. MySQLi: Modo de error patrón definido como excepciones.
  7. Conversión implícita incompatible de float para int está obsoleta.
  8. Extensión finfo: recursos de file_info migrados para objetos finfo existentes.
  9. IMAP: recursos imap migrados para objetos de clase IMAP\Connection.
  10. Extensión FTP: Recursos de conexión migrados a objetos de clase FTP\Connection.
  11. Extensión GD: Identificadores de fuentes migrados para objetos de clase GdFont.
  12. LDAP: recursos migrados para objetos de classe LDAP\Connection, LDAP\Result y LDAP\ResultEntry.
  13. PostgreSQL: recursos migrados a objetos de clase PgSql\Connection, PgSql\Result y PgSql\Lob.
  14. Pspell: recursos pspell y pspell config migrados a objetos de clase PSpell\Dictionary y PSpell\Config.

A través del sitio web de la versión, puedes comprender mejor las desaprobaciones y eliminaciones, así como acceder a documentación más completa sobre las nuevas funciones.

Link para el site de la versión: https://www.php.net/releases/8.1/en.php


Conclusión

Son 28 años desarrollando un lenguaje sólido, mantenido por colaboradores de todo el mundo y con uso global.

La nueva versión trajo muchas características esperadas por muchos desarrolladores, así como importantes mejoras de rendimiento.

Las versiones 8.2 y 8.3 también prometen traer excelentes actualizaciones al idioma, que se tratarán en los próximos artículos.

Como desarrolladores, debemos estar siempre al tanto de las actualizaciones tecnológicas. Saber exactamente cómo utilizar todas las funciones de un lenguaje puede ayudarle a ser mucho más productivo y escribir mejor código.

Espero que os haya gustado, gracias y ¡hasta la próxima!

💡
Las opiniones y comentarios emitidos en este artículo son propiedad única de su autor y no necesariamente representan el punto de vista de Listopro.

Listopro Community da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.