PHP 8.2: readonly classes, DNF types, constantes tipadas y deprecaciones

PHP 8.2 llegó en noviembre de 2022 con varias mejoras centradas en la inmutabilidad y la seguridad del sistema de tipos. Aquí están las novedades más importantes con ejemplos directos.

Readonly classes

Antes de PHP 8.2, para crear un objeto inmutable tenías que marcar cada propiedad como readonly. Ahora puedes marcar la clase entera:

<?php
// PHP 8.1: tedioso
class PuntoViejo
{
    public function __construct(
        public readonly float $x,
        public readonly float $y,
        public readonly float $z,
    ) {}
}

// PHP 8.2: limpio
readonly class Punto
{
    public function __construct(
        public float $x,
        public float $y,
        public float $z,
    ) {}
}

$p = new Punto(1.0, 2.0, 3.0);
// $p->x = 5.0;  // Error: Cannot modify readonly property
?>

Las readonly classes solo pueden tener propiedades tipadas; no admiten propiedades estáticas ni propiedades sin tipo.

Tipos DNF (Disjunctive Normal Form)

PHP 8.2 permite combinar tipos de intersección con uniones siguiendo la forma normal disyuntiva:

<?php
interface Serializable {}
interface Loggable {}

function procesarONull((Serializable&Loggable)|null $obj): void
{
    if ($obj === null) {
        echo "Nulon";
        return;
    }
    // Aquí $obj implementa AMBAS interfaces
    echo get_class($obj) . "n";
}
?>

La sintaxis requiere que los grupos de intersección vayan entre paréntesis: (A&B)|C.

Constantes tipadas en clases

<?php
class Estado
{
    const string ACTIVO   = 'activo';
    const string INACTIVO = 'inactivo';
    const int    MAX_INTENTOS = 5;
    const float  DESCUENTO_VIP = 0.15;
}

echo Estado::ACTIVO;       // 'activo'
echo Estado::MAX_INTENTOS; // 5
?>

El tipo se comprueba en tiempo de compilación: asignar un valor del tipo incorrecto causa un error fatal.

true, false y null como tipos standalone

En PHP 8.0 se añadieron como parte de uniones. En PHP 8.2 pueden usarse solos:

<?php
function deshabilitado(): false
{
    return false;
}

function sinRetorno(): null
{
    // equivale a void pero permite que return null; sea explícito
    return null;
}

function siempreVerdadero(): true
{
    return true;
}
?>

Atributo SensitiveParameter

Oculta valores de parámetros en stack traces, muy útil para contraseñas y tokens:

<?php
function conectar(
    string $host,
    string $user,
    #[SensitiveParameter] string $password
): void {
    // Si esto lanza una excepción, $password aparecerá como Object(SensitiveParameterValue)
    throw new RuntimeException("Fallo al conectar con $host");
}

try {
    conectar('db.ejemplo.com', 'admin', 'MiContraseñaSecreta');
} catch (RuntimeException $e) {
    // En el stack trace: conectar('db.ejemplo.com', 'admin', Object(SensitiveParameterValue))
    echo $e->getMessage();
}
?>

Deprecaciones en PHP 8.2

  • Propiedades dinámicas: asignar propiedades no declaradas en una clase lanza E_DEPRECATED. En PHP 9.0 será un error fatal. Usa el atributo #[AllowDynamicProperties] para mantener el comportamiento antiguo.
  • Funciones utf8_encode() y utf8_decode(): marcadas como deprecated. Usa mb_convert_encoding() en su lugar.
  • Funciones de la extensión ODBC con parámetros null: varias funciones dejarán de aceptar null donde esperaban string.
<?php
// PHP 8.2: E_DEPRECATED
class Viejo
{
    public function prueba(): void
    {
        $this->propiedadDinamica = 'valor'; // deprecated
    }
}

// Solución: declara la propiedad o usa el atributo
#[AllowDynamicProperties]
class ConPermiso
{
    // Propiedades dinámicas permitidas explícitamente
}
?>

Mejoras menores

  • RandomRandomizer: nueva clase en la extensión random introducida en 8.2 con métodos más ergonómicos que las funciones globales.
  • Traits con constantes: PHP 8.2 permite definir constantes en traits (aunque con algunas limitaciones de acceso).
  • Mejoras en el rendimiento del motor Zend: reducción de uso de memoria y mayor velocidad en operaciones con arrays y strings.

Resumen rápido

CaracterísticaAntesPHP 8.2
Objetos inmutablesreadonly en cada propiedadreadonly class
Tipos combinadossolo A&B o A|B(A&B)|C (DNF)
Constantes tipadassin tipoconst string/int/float...
Datos sensiblessin soporte#[SensitiveParameter]

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP