Qué hay de nuevo en PHP8.2

La última versión de PHP trae características que le siguen haciendo más moderno y versátil. Desde el lanzamiento de PHP8.0 han habido numerosas mejoras en un lenguaje que es cada vez más maduro.

Readonly classes

En PHP8.1 se podían crear atributos de solo lectura en una clase. Desde PHP8.2, se pueden crear clases readonly, haciendo todos sus atributos de sólo lectura de forma implícita.

readonly class Post {
	public function __construct(
    	public string $title,
        public string $description
    ){
    	// ...
    }
}

$post = new Post(
	title: 'Título del post',
    description: 'Lorem ipsum dolor sit amet'
);
$post->title = 'Otro título'; // Excepción: Cannot modify readonly property

$post->otra_propiedad = 'Test'; // Excepción: Cannot create dynamic property

Atributo AllowDynamicProperties

Uno de los cambios más controvertidos de PHP8.2 es la deshabilitación de las propiedades dinámicas por defecto en el lenguaje. Esta característica ha sido muy usada por muchos frameworks y librerías, pero traía muchas consecuencias negativas en el mantenimiento del lenguaje.

class User {}

$user = new User();
$user->foo = 'bar';

Desde PHP8.2 esto ya no será posible, sino que habrá que definir el atributo foo de forma explícita en la clase.

En caso de necesitar seguir usando las propiedades dinámicas, se puede usar un atributo en la definición de la clase para indicar al lenguaje que en ese caso están permitidas:

#[AllowDynamicProperties]
class User {}

$user = new User();
$user->foo = 'bar';

Nuevos tipos de respuesta

Ahora existe también el tipo false, true y null para las funciones que devuelvan uno de estos valores de forma constante.

function alwaysReturnsFalse(): false {}

function alwaysReturnsNull(): null {}

function alwaysReturnsTrue(): true {}

Constantes en traits

Desde PHP8.2 ya es posible declarar constantes en traits:

trait FooBar {
    const FOO = 'foo';
    private const BAR = 'bar';
    final const BAZ = 'baz';
    final protected const QUX = 'qux';
}

class Test {
    use FooBar;
}

echo Test::BAZ; // 'bar'

Parámetros sensibles

Imagina que tenemos una función que recibe, por ejemplo, una contraseña de un usuario. Si esa función devolviera una excepción, los logs del servidor guardarían esa contraseña al guardar el stacktrace. Para evitar esto, podemos usar el atributo #[\SensitiveParameter]

function passwordHash(#[\SensitiveParameter] string $password)  {
	debug_print_backtrace();
}

Al guardar el trace en los logs, se guardaría algo así:

array(1) {
    [0]=> array(4) {
        ["file"]=> string(38) "..."
        ["line"]=> int(9)
        ["function"]=> string(3) "foo"
        ["args"]=> array(1) {
             [0]=> string(38) "hunter2"
             [0]=> object(SensitiveParameterValue)#1 (0) {}
  		}
	}
}

Hay más cambios menores y algunas funcionalidades deprecadas. Podemos verlas todas en PHP.watch.