Attributi in PHP 8

Maico Orazio
weBeetle
Published in
4 min readJun 27, 2023

--

PHP 8 ha introdotto molte nuove funzionalità interessanti, tra queste vanno necessariamente menzionati gli attributi. Gli attributi sono simili ai commenti di documentazione, ma possono essere utilizzati per indicare informazioni più specifiche sulle classi, i metodi e le proprietà.

Per descrivere al meglio gli attributi di PHP è necessario introdurre un concetto propedeutico alla loro comprensione: la Reflection.

La reflection è la capacità di un programma di eseguire delle elaborazioni che hanno per oggetti il programma stesso: con la reflection abbiamo la possibilità di introspezionare classi, interfacce, funzioni, metodi; ovvero, possiamo capire quali metodi ha una classe, quali argomenti ha un metodo e così via. Questa premessa ci serve proprio perché gli attributi sono recuperabili grazie alla reflection.

Gli attributi in PHP ci permettono di aggiungere dei metadati alle dichiarazioni di classi, metodi, funzioni, parametri, proprietà e costanti. I metadati diventano così degli elementi strutturati ed interpretabili.

Prima degli attributi si utilizzavano le annotations. Si otteneva il loro contenuto sempre attraverso la reflection, però rimaneva una stringa che doveva poi essere interpretata. Invece con gli attributi abbiamo la possibilità di scrivere del vero codice direttamente interpretabile senza la necessità di andare a decodificarlo.

Il nome dell’attributo rappresenta la classe. Gli argomenti, opzionali, rappresentano i parametri definiti nel costruttore della classe. Ad esempio, è possibile utilizzare gli attributi per indicare se una classe è stata deprecata e fornire informazioni su come utilizzare la classe sostitutiva:

#[Deprecated('Questa classe è deprecata. Si prega di utilizzare la classe MyClass al suo posto.')]
class MyOldClass
{
// codice della classe
}

In questo esempio, l’attributo #[Deprecated] viene utilizzato per indicare che la classe MyOldClass è deprecata. Il messaggio di deprecazione specificato, viene visualizzato come avviso nel codice e nei log, per informare che la classe non è più consigliata e dovrebbe essere sostituita con MyClass.

Esempio pratico di attributo applicato alle classi

Ecco un esempio custom di utilizzo degli attributi in PHP 8:

#[MyCustomAttribute('questo è un attributo personalizzato')]
class MyClass
{
// codice della classe
}

In questo esempio, abbiamo definito un attributo personalizzato chiamato MyCustomAttribute che può essere applicato a una classe. L’attributo riceve un parametro stringa, che viene utilizzato per specificare un messaggio personalizzato.

Possiamo definire il nostro attributo personalizzato creando una classe che estende la classe Attribute di PHP 8, come mostrato di seguito:

#[Attribute]
class MyCustomAttribute
{
private string $message;

public function __construct(string $message)
{
$this->message = $message;
}

public function getMessage(): string
{
return $this->message;
}
}

Abbiamo definito un costruttore che accetta una stringa per impostare il messaggio personalizzato, e un metodo getMessage per recuperare il messaggio.

Possiamo quindi applicare l’attributo personalizzato alle classi, come mostrato nell’esempio precedente. Quando applichiamo l’attributo, possiamo passare un messaggio personalizzato come parametro e recuperarlo utilizzando il metodo getMessage.

Esempio pratico di attributo applicato alle proprietà

Supponiamo di avere una classe Product che rappresenta un prodotto in un negozio online. La classe ha alcune proprietà come name, price e description e alcuni metodi per recuperare e impostare questi valori:

class Product 
{
private string $name;
private float $price;
private string $description;

public function __construct(
string $name,
float $price,
string $description
)
{
$this->name = $name;
$this->price = $price;
$this->description = $description;
}

public function getName(): string
{
return $this->name;
}

public function setName(string $name): void
{
$this->name = $name;
}

public function getPrice(): float
{
return $this->price;
}

public function setPrice(float $price): void
{
$this->price = $price;
}

public function getDescription(): string
{
return $this->description;
}

public function setDescription(string $description): void
{
$this->description = $description;
}
}

Ora supponiamo di indicare che la proprietà price non possa essere impostata con un valore negativo. Possiamo utilizzare un attributo personalizzato per indicare questa restrizione.

Per fare questo, definiamo un attributo personalizzato PositiveValue che controlla se il valore passato è maggiore di zero. Se il valore è inferiore o uguale a zero, viene sollevata un’eccezione.

#[Attribute]
class PositiveValue
{
public function __construct()
{
}

public function __invoke($value)
{
if ($value <= 0) {
throw new InvalidArgumentException("Il valore deve essere maggiore di zero");
}
}
}

L’attributo PositiveValue è una classe che estende la classe Attribute e ha un metodo magico __invoke che viene chiamato quando l’attributo viene applicato alla proprietà price. Questo metodo accetta il valore della proprietà e verifica se è inferiore o uguale a zero, nel caso, solleva un’eccezione.

Possiamo applicarlo alla proprietà price come segue:

class Product 
{
private string $name;

#[PositiveValue]
private float $price;

private string $description;

public function __construct(
string $name,
float $price,
string $description
)
{
$this->name = $name;
$this->price = $price;
$this->description = $description;
}

// altri metodi
}

Quando viene creato un nuovo oggetto Product, l’attributo PositiveValue viene applicato alla proprietà price. Se si tenta di impostare un valore negativo per price, verrà sollevata un’eccezione.

Questi sono solo alcuni esempi di come gli attributi possono essere utili per indicare informazioni specifiche sulle classi, le proprietà e i metodi in modo da semplificare la gestione del codice.

Buon lavoro 👨‍💻

--

--

Maico Orazio
weBeetle

Senior Web Application Developer. I'm a software engineer, a passionate coder, and a web developer. I am a fan of technology. #php #symfony #javascript #reactjs