PHP 8.3 está disponible desde finales de Noviembre del 2023. En esta versión se continúa la tendencia de introducir mejoras en el sistema de tipos, y como es usual, se añaden clases, interfaces y funciones nuevas, algunos de los cambios que se introducen son incompatibles con versiones anteriores. Veremos las novedades más importantes a continuación:

Constantes de clase tipadas

Se introduce soporte para constantes de clase tipadas, con esto podemos asegurarnos de que se mantenga la compatibilidad de tipos de datos en una constante cuando sea sobre-escrita dentro de una clase hija. Cualquier intento de sobrescribir el valor o el tipo de dato de una constante de clase tipada arrojará un error fatal si el valor o tipo de dato no son compatibles por el declarado en la clase o interfaz principal.

interface I
{
  // Constante de clase de tipo cadena
  const string PHP = 'PHP 8.3';
}

class Foo implements I
{
  const PHP = [];
  // Se sobrescribe la constante de cadena como un arreglo
  // PHP devuelve un error fatal
}

Nuevo atributo #[\Override]

Al añadir el nuevo atributo #[\Override] a un método, PHP se asegurará de que exista un método con el mismo nombre en una clase padre o en alguna interfaz implementada. Es decir, que el método sobrescriba o implemente un método padre o de interfaz, de lo contrario PHP arrojará un error fatal.

Añadir el atributo deja clara la intención de anular un método padre.

Esto facilita la refactorización al detectar la eliminación de un método padre anulado. Previniendo llamadas accidentales a métodos mal escritos y ayuda a detectar la eliminación de un método importante en la clase o interfaz padre.

Caso 1: El método sobrescribe otro método del mismo nombre en la clase padre.

class Padre
{
  public function miMetodo(): void {}
}

class Hija extends Padre
{
  #[\Override]
  public function miMetodo(): void {
    print "Hola mundo!";
  }
}

Caso 2: Si el nombre del método que usa el atributo #[override] no sobrescribe ningún método de la clase padre.

class Padre
{
  public function primerMetodo(): void {}
}

class Hija extends Padre
{
  #[\Override]
  public function segundoMetodo(): void {
    print "Hola mundo!";
  }
}

// PHP Devuelve un error fatal porque el método con atributo #[\Override] no sobrescribe un método de una clase padre

Extracción dinámica de constantes de clase

A partir de PHP >= 8.3 se incuye soporte para extraer constantes de clases y objetos de enumeración dinámicamente con el nombre de la variable, eliminando la necesidad de llamar al método constant().

class Foo
{
  const SALUDO = 'Hola';
}

$nombre_de_constante = 'SALUDO';

// Recuperando la constante de clase
var_dump( Foo::{$nombre_de_constante} );

Nueva función: json_validate

Podemos utilizar la función booleana json_validate para comprobar si una cadena de texto contiene JSON válido. Esta alternativa utiliza menos memoria que json_decode dado que la validación solo comprueba la sintaxis sin tener que construir un arreglo o la estructura del objeto que contenga la carga.

$cadena_valida = '{ "test": { "foo": "bar" } }';
$cadena_invalida = '( test",%#$ { "foo": "bar" } }';

var_dump(json_validate($cadena_valida)); // devuelve true
var_dump(json_validate($cadena_invalida)); // devuelve false

Clonación profunda de propiedades de solo lectura

Ahora las propiedades de clases de solo lectura pueden modificarse una vez dentro del método mágico __clone, para hacer posible el clonado profundo de clases de solo lectura.

Anteriormente al clonar una clase de solo lectura, PHP creaba una referencia a las propiedades de la clase original en la clase clonada. Esto provocaba que al cambiar el valor de una propiedad en la clase original o en la clonada, se modificara el valor en ambas clases.

A partir de esta versión podemos clonar las propiedades de la clase original dentro del método mágico __clone, creando una propiedad nueva dentro del clon en vez de solo asignar una referencia a la propiedad original. De esta manera podemos realizar cambios independientes en las propiedades de la clase.

class PHP
{
  public string $version = '8.2';
}

readonly class Foo
{
  public function __construct( public PHP $php ) {}

  // Método mágico __clone
  public function __clone(): void
  {
    $this->php = clone $this->php;
  }
}

$instancia = new Foo(new PHP());
$clon = clone $instancia;

// Reasignación del valor de la propiedad en la clase clon
$clon->php->version = '8.3';

$instancia->php->version; // 8.2
// El valor de la clase original se mantiene sin cambios

$clonado->php->version; // 8.3
// El valor de la clase clonada refleja el cambio realizado anteriormente

Soporte para linter a múltiples archivos desde la línea de comandos

La herramienta de linter disponible en la línea de comando ahora procesa todos los archivos que reciba como argumentos, en versiones anteriores el linter solo tomaba el primer archivo para procesar e ignoraba el resto de los argumentos.

php -l foo.php bar.php

No syntax errors detected in foo.php
No syntax errors detected in bar.php

Nuevas clases, interfaces y funciones

Extensiones DOM:

  • Métodos:
    • DOMElement::getAttributeNames()
    • DOMElement::insertAdjacentElement()
    • DOMElement::insertAdjacentText()
    • DOMElement::toggleAttribute()
    • DOMNode::contains()
    • DOMNode::getRootNode()
    • DOMNode::isEqualNode()
    • DOMNameSpaceNode::contains()
    • DOMParentNode::replaceChildren()

Extensiones Intl:

  • Métodos:
    • IntlCalendar::setDate()
    • IntlCalendar::setDateTime()
    • IntlGregorianCalendar::createFromDate()
    • IntlGregorianCalendar::createFromDateTime()

Extensión LDAP:

  • Funciones:
    • ldap_connect_wallet()
    • ldap_exop_sync()

Extensión mbstring:

  • Funciones:
    • mb_str_pad()

Extensión POSIX:

  • Funciones:
    • posix_sysconf()
    • posix_pathconf()
    • posix_fpathconf()
    • posix_eaccess()

Extensión Reflection:

  • Método:
    • ReflectionMethod::createFromMethodName()

Extensión de sockets:

  • Función:
    • socket_atmark()

Otras adiciones:

  • Funciones:
    • str_increment()
    • str_decrement()
    • stream_context_set_options()
  • Método:
    • ZipArchive::getArchiveFlag()
  • Soporte para generación de claves EC con parámetros personalizados en la extensión OpenSSL.
  • Nueva configuración INI zend.max_allowed_stack_size para configurar el tamaño máximo del stack.
  • Ahora php.ini soporta sintaxis de valores fallback/default.
  • Ahora las clases anónimas tambien pueden ser declaradas como de solo lectura.

Cambios no retrocompatibles

  • Asignar un índice negativo n a un arreglo vacío ahora asegurará que el siguiente índice es n + 1 en vez de 0.
  • Cambios a la función range().
  • Cambios a la redeclaración de propiedades estáticas en rasgos (traits).
  • La constante U_MULTIPLE_DECIMAL_SEPERATORS fue descontinuada en favor de U_MULTIPLE_DECIMAL_SEPARATORS.
  • La variante MT_RAND_PHP Mt19937 es obsoleta.
  • ReflectionClass::getStaticProperties() ya no admite null.
  • Las configuraciones INI assert.active, assert.bail, assert.callback, assert.exception, y assert.warning fueron marcadas como obsoletas.
  • Llamar las funciones get_class() y get_parent_class() sin pasar argumentos ya no está soportado.
  • SQLite3: Se cambió el modo de error por defecto a excepciones.

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Novedades de PHP 8.2