PHP 8.3: constantes tipadas en clases, #[Override] y mejoras en json_validate

PHP 8.3 se publicó en noviembre de 2023 y continúa refinando el sistema de tipos y añadiendo herramientas que reducen errores difíciles de detectar. Las novedades principales son constantes tipadas en clases e interfaces, el atributo #[Override] y json_validate().

Constantes tipadas en clases e interfaces

Ya disponible en PHP 8.2 para clases, en 8.3 se extiende a interfaces y traits:

<?php
interface EstadoPedido
{
    const string PENDIENTE  = 'pendiente';
    const string PROCESANDO = 'procesando';
    const string ENVIADO    = 'enviado';
    const string ENTREGADO  = 'entregado';
}

class GestorPedido implements EstadoPedido
{
    public function cambiarEstado(string $estado): void
    {
        if (!in_array($estado, [self::PENDIENTE, self::PROCESANDO, self::ENVIADO, self::ENTREGADO])) {
            throw new ValueError("Estado '$estado' no válido");
        }
        // ...
    }
}
?>

Atributo #[Override]

Marca un método como sobreescritura de la clase padre. PHP 8.3 verifica que el método realmente exista en la clase padre; si no, lanza un error fatal. Elimina la categoría de bugs donde renombras un método en la clase base pero olvidas actualizarlo en las subclases:

<?php
class Animal
{
    public function hacerSonido(): string
    {
        return '...';
    }
}

class Perro extends Animal
{
    #[Override]
    public function hacerSonido(): string  // OK: existe en Animal
    {
        return 'Guau';
    }

    #[Override]
    public function correr(): void  // ERROR FATAL: Animal no tiene correr()
    {
        // Fatal error: Perro::correr() has #[Override] attribute, but no matching parent method exists
    }
}
?>

json_validate()

Valida si un string es JSON válido sin decodificarlo, mucho más eficiente que json_decode() + json_last_error():

<?php
// PHP 8.3
$json = '{"nombre": "Ana", "edad": 30}';

if (json_validate($json)) {
    $datos = json_decode($json, true);
    echo $datos['nombre'];
}

// Comparación de rendimiento (solo validar, sin decodificar)
$grande = file_get_contents('datos-grandes.json');

// Antes: decodifica todo para saber si es válido
json_decode($grande);
$valido = json_last_error() === JSON_ERROR_NONE;

// PHP 8.3: solo valida, no carga en memoria
$valido = json_validate($grande);  // mucho más rápido y eficiente
?>

Acceso dinámico a constantes de clase

<?php
class Colores
{
    const string ROJO  = 'rojo';
    const string AZUL  = 'azul';
    const string VERDE = 'verde';
}

$constante = 'ROJO';
echo Colores::{$constante};  // 'rojo'

// Útil para mapear strings a constantes
function obtenerColor(string $nombre): string
{
    return Colores::{strtoupper($nombre)};
}

echo obtenerColor('azul');  // 'azul'
?>

Nuevos métodos en RandomRandomizer

<?php
$rand = new RandomRandomizer();

// PHP 8.3: getBytesFromString()
$token = $rand->getBytesFromString('abcdefghijklmnopqrstuvwxyz0123456789', 32);
echo $token; // cadena aleatoria de 32 caracteres del alfabeto dado

// PHP 8.3: getFloat() y nextFloat()
$precio = $rand->getFloat(10.0, 100.0);            // float entre 10 y 100
$prob   = $rand->getFloat(0.0, 1.0, RandomIntervalBoundary::ClosedOpen);
?>

Readonly properties en clases anónimas

<?php
$punto = new readonly class(1.5, 2.5) {
    public function __construct(
        public float $x,
        public float $y,
    ) {}
};

echo "{$punto->x}, {$punto->y}";  // 1.5, 2.5
?>

Clases con herencia: #[Override] en interfaces

<?php
interface Formateador
{
    public function formatear(mixed $valor): string;
}

class FormateadorMoneda implements Formateador
{
    #[Override]
    public function formatear(mixed $valor): string  // Verifica que existe en la interfaz
    {
        return number_format((float)$valor, 2, ',', '.') . ' €';
    }
}
?>

Deprecaciones y cambios en PHP 8.3

  • Llamadas a métodos estáticos en un objeto instanciado: ya deprecated en versiones anteriores, en 8.3 genera E_DEPRECATED.
  • Modificar arrays durante un foreach por referencia: comportamiento más estricto y predecible.
  • unserialize() con clases no encontradas: emite E_WARNING en lugar de silenciarlo.

Resumen de PHP 8.3

NovedadQué resuelve
Constantes tipadas en interfacesContratos más seguros entre clases
#[Override]Detecta métodos huérfanos al refactorizar
json_validate()Validación JSON eficiente sin deserializar
Constantes dinámicasAcceso flexible a constantes en runtime
getBytesFromString()Tokens aleatorios con alfabeto controlado

COMPARTE ESTE ARTÍCULO

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