Nelle classi PHP è possibile impostare e recuperare dinamicamente le proprietà della classe che non sono dichiarate. Queste proprietà non aderiscono a uno specifico (simile alle proprietà tipizzate) e richiedono l’uso dei metodi magici __get() e __set() per prevenire o controllare in modo efficace il modo in cui le proprietà dinamiche vengono impostate e recuperate.
class User { private int $uid; } $user = new User(); $user->name = 'Foo';
deprecated: Creation of dynamic property User::$name is deprecated in … on line …
L’impostazione delle proprietà dall’interno della classe emette anche l’avviso di deprecazione:
class User { public function __construct() { $this->name = 'test'; } } new User();
Deprecated: Creation of dynamic property User::$name is deprecated in … on line …
Esistono casi d’uso legittimi di proprietà dinamiche, come oggetti valore derivati da una risposta JSON dinamica o oggetti di configurazione che consentono valori arbitrari.
Modelli di proprietà dinamici esentati
Ci sono tre eccezioni a questa deprecazione. Utilizzando uno degli approcci seguenti si evita l’avviso di deprecazione.
- Classi con l’attributo #[AllowDynamicProperties].
- stdClass e le sue sottoclassi
- Classi con metodi magici __get e __set
Classi con l’attributo #[AllowDynamicProperties].
PHP 8.2 introduce un nuovo attributo nello spazio dei nomi globale denominato #[AllowDynamicProperties]. Le classi dichiarate con questo attributo segnalano a PHP di non emettere alcun avviso di deprecazione quando si impostano proprietà dinamiche sugli oggetti di quella classe.
Lo snippet seguente dichiara una classe Utente con l’attributo #[AllowDynamicProperties] e non emette alcun avviso di deprecazione anche se imposta le proprietà in modo dinamico.
#[AllowDynamicProperties] class User { private int $uid; } $user = new User(); $user->name = 'Foo';
stdClass e le sue sottoclassi
PHP utilizza stdClass come classe base quando trasferisce i dati in oggetti, quando decodifica oggetti JSON, ecc. In PHP 8.2, l’attributo #[AllowDynamicProperties] viene aggiunto internamente alla classe stdClass. Ciò significa che l’impostazione delle proprietà dinamiche sugli oggetti stdClass o su qualsiasi classe che estenda stdClass non emette avvisi di deprecazione delle proprietà dinamiche.
$object = new stdClass(); $object->foo = 'bar'; class User extends stdClass {} $object = new User(); $object->foo = 'bar';
Neither of the snippets above emit dynamic property deprecation notices because the stdClass internally has the #[AllowDynamicProperties] attribute.
Classes with __get and __set magic methods
Classes that declare a __set magic method are excluded from the dynamic property declaration. It might be necessary to couple it with a __get
method to create a practically useful class.
class User { public function __set(string $name, mixed $value): void { } } $user = new User(); $user->name = 'test';
Lo snippet sopra non emette un avviso di deprecazione perché la classe User implementa il metodo magico __set
.
Tieni presente che l’impostazione di una proprietà dinamica dal metodo __set
è ancora deprecata:
Associazione dei dati degli oggetti a WeakMaps
PHP 8.0 ha introdotto WeakMaps in PHP. Le applicazioni che impostano proprietà dinamiche per associare dati ausiliari possono prendere in considerazione l’utilizzo di WeakMaps. Ciò potrebbe migliorare la chiarezza e la manutenibilità del codice, evitando l’avviso di deprecazione della proprietà dinamica.
Ad esempio, il frammento seguente memorizza una proprietà dinamica denominata elaborata. Questa proprietà non è dichiarata nella classe Event e non appartiene alla classe Event stessa.
$event = new Event(); $event->processed = true; // <-- dynamic property $is_processed = !empty($event->processed);
Con WeakMap è possibile associare i dati in una WeakMap. Quando l’oggetto Evento viene eliminato dall’ambito, i dati associati verranno rimossi automaticamente.
$event = new Event(); $processed_events = new WeakMap(); $event->processed = true; // <-- dynamic property $processed_events[$event] = true; $is_processed = !empty($event->processed); $is_processed = !empty($processed_events[$event]);
Impatto sulla compatibilità con le versioni precedenti
L’avviso di deprecazione viene emesso su PHP 8.2 e versioni successive. In PHP 9.0, le proprietà dinamiche comporteranno un errore fatale.
È possibile emettere a livello di codice una deprecazione nelle versioni precedenti nell’interesse della coerenza tra più versioni PHP.