Released!

PHP 8.1 es una actualización importante del lenguaje PHP.
Contiene muchas características nuevas y mejoradas, incluyendo enumeraciones, propiedades de solo lectura, sintaxis first-class callable, fibers, tipos de intersección, mejoras de rendimiento y más.

Enumeraciones

Use enum en lugar de un conjunto de constantes y obtenga la validación lista para su uso.

PHP < 8.1
class Status
{
    const DRAFT = 'draft';
    const PUBLISHED = 'published';
    const ARCHIVED = 'archived';
}
function acceptStatus(string $status) {...}
PHP 8.1 RFC Doc
enum Status
{
    case Draft;
    case Published;
    case Archived;
}
function acceptStatus(Status $status) {...}

Propiedades de solo lectura

Las propiedades de solo lectura no se pueden cambiar después de la inicialización, es decir, después de que se les asigne un valor. Son una excelente manera de modelar objetos de valor y objetos de transferencia de datos.

PHP < 8.1
class BlogData
{
    private Status $status;

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

    public function getStatus(): Status
    {
        return $this->status;
    }
}
PHP 8.1 RFC Doc
class BlogData
{
    public readonly Status $status;

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

Sintaxis First-class Callable

Ahora es posible obtener una referencia a cualquier función; esto se llama sintaxis First-class Callable.

PHP < 8.1
$foo = [$this, 'foo'];

$fn = Closure::fromCallable('strlen');
PHP 8.1 RFC Doc
$foo = $this->foo(...);

$fn = strlen(...);

Expresión New en constructor

Los objetos instanciados pueden ahora se utilizados como parámetros por defecto, así como variables estáticas, constantes globales, así como argumentos de atributos.

Esto efectivamente permite usar atributos anidados.

PHP < 8.1
class Service
{
    private Logger $logger;

    public function __construct(
        ?Logger $logger = null,
    ) {
        $this->logger = $logger ?? new NullLogger();
    }
}
PHP 8.1 RFC
class Service
{
    private Logger $logger;

    public function __construct(
        Logger $logger = new NullLogger(),
    ) {
        $this->logger = $logger;
    }
}
PHP < 8.1
class User
{
    /**
     * @Assert\All({
     *     @Assert\NotNull,
     *     @Assert\Length(min=5)
     * })
     */
    public string $name = '';
}
PHP 8.1
class User
{
    #[\Assert\All(
        new \Assert\NotNull,
        new \Assert\Length(min: 5))
    ]
    public string $name = '';
}

Tipos de intersección pura

Utilice tipos de intersección cuando un valor necesite resolver varias restricciones de tipado al mismo tiempo.

Actualmente no es posible mezclar tipos de intersección y unión como A&B|C.

PHP < 8.1
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);
}
PHP 8.1 RFC Doc
function count_and_iterate(Iterator&Countable $value) {
    foreach ($value as $val) {
        echo $val;
    }

    count($value);
}

Tipo de retorno Never

Una función o método declarado con el tipo never indica que no devolverá un valor y producirá una excepción o finalizará la ejecución del script con una llamada de die(), exit(), trigger_error(), o similar.

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

function redirectToLoginPage() {
    redirect('/login');
    echo 'Hello'; // <- dead code
}
PHP 8.1 RFC Doc
function redirect(string $uri): never {
    header('Location: ' . $uri);
    exit();
}

function redirectToLoginPage(): never {
    redirect('/login');
    echo 'Hello'; // <- dead code detected by static analysis
}

Constantes de clase final

Es posible declarar la constante final en la clase, para que no puedan ser sobreescrita en las clases heredadas.

PHP < 8.1
class Foo
{
    public const XX = "foo";
}

class Bar extends Foo
{
    public const XX = "bar"; // No error
}
PHP 8.1 RFC Doc
class Foo
{
    final public const XX = "foo";
}

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

Notación numérica octal explícita

Ahora es posible escribir números octales con el prefijo explícito 0o.

PHP < 8.1
016 === 16; // false because `016` is octal for `14` and it's confusing
016 === 14; // true
PHP 8.1 RFC Doc
0o16 === 16; // false — not confusing with explicit notation
0o16 === 14; // true

Fibers

Fibers es la forma primitiva para la implementación ligera de concurrencia. Son un medio para crear bloques de código que se puedan pausarse y reanudarse como generadores (Generators), pero desde cualquier lugar de la pila. Los Fibers en sí mismo, no proporcionan la concurrecia mágicamente, todavía se necesita tener un bucle de eventos. Sin embargo, permiten que las implementaciones de bloqueo y no-bloqueo compartan la misma API.

Los Fibers permiten deshacerse del código repetitivo visto anteriormente con Promise::then() o las corutinas basadas en el generador (Generator). Las bibliotecas generalmente construirán más abstracciones alrededor de Fibers, por lo que no hay necesidad de interactuar con ellas directamente.

PHP < 8.1
$httpClient->request('https://example.com/')
        ->then(function (Response $response) {
            return $response->getBody()->buffer();
        })
        ->then(function (string $responseBody) {
            print json_decode($responseBody)['code'];
        });
PHP 8.1 RFC Doc
$response = $httpClient->request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];

Soporte de desestructuración de Arrays

PHP soportaba la desestructuración de Arrays, pero solo si el Array tenía keys de tipo integer. Ahora también es posible la desestructuración de Arrays con keys de tipo string.

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

$result = array_merge(['a' => 0], $arrayA, $arrayB);

// ['a' => 1, 'b' => 2]
PHP 8.1 RFC Doc
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];

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

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

Mejoras de rendimiento

Aplicación de demostración de Symfony - tiempo de solicitudes
25 ejecuciones consecutivas, 250 solicitudes (seg)
(menos es mejor)

El resultado (en relación con PHP 8.0):

  • La aplicación de demostración de Symfony es 23.0% más rápida
  • Un sitio WordPress es 3.5% más rápido

Características relacionadas con el rendimiento en PHP 8.1:

  • JIT backend para ARM64 (AArch64)
  • Caché heredado (Evite volver a vincular clases en cada solicitud)
  • Resolución rápida de nombres de clases (evita la resolución de nombres en minúscula y la búsqueda vía hash)
  • Mejoras en el rendimiento de timelib and ext/date
  • Mejoras en los iteradores del sistema de archivos SPL
  • Optimización en serialize/unserialize
  • Optimización de algunas funciones internas (get_declared_classes(), explode(), strtr(), strnatcmp(), dechex())
  • Mejoras y correcciones de JIT

Nuevas clases, interfaces y funciones

  • Nuevo atributo #[ReturnTypeWillChange].
  • Nuevas funciones fsync y fdatasync.
  • Nueva función array_is_list.
  • Nuevas funciones para Sodium XChaCha20.

Obsolescencias y la falta de compatibilidad con versiones anteriores

  • Pasar null como parámetro en funciones internas non-nullable queda obsoleto.
  • Tipos de retorno en los métodos de clase integrados de PHP
  • Interfaz Serializable es obsoleta.
  • Las funciones de entidad HTML en/decode procesan comillas simples y son sustituidas por defecto.
  • Restricciones en la variable $GLOBALS.
  • MySQLi: Modo de error predeterminado establecido en excepciones.
  • La conversión implícita incompatible de float a int es obsoleta.
  • Extensión finfo: recursos de file_info migrado a objetos finfo existentes.
  • IMAP: imap resources migrated to IMAP\Connection class objects.
  • Extensión FTP: Recursos de conexión migrados a la clase FTP\Connection.
  • Extensión GD: Los indetificadores de fuentes (Font) migrados a la clase GdFont.
  • LDAP: recursos migrados a las clases LDAP\Connection, LDAP\Result, y LDAP\ResultEntry.
  • PostgreSQL: recursos migrados a las clases PgSql\Connection, PgSql\Result, y PgSql\Lob.
  • Pspell: los recursos de configuración de pspell y pspell han sido migrados a las clases PSpell\Dictionary, PSpell\Config.
To Top