In questa lezione analizziamo i principali cambiamenti introdotti nelle versioni moderne di PHP, con particolare attenzione al sistema di tipizzazione. L’obiettivo non è “conoscere le novità”, ma capire come queste modificano il modo di progettare e scrivere codice in contesti professionali.ù
Cosa è cambiato nel paradigma di PHP tra la versione 7 e la 8?
Durante il tormentato periodo del Covid, alla fine di novembre 2020, è stato rilasciato PHP 8. Il linguaggio ha subito una trasformazione importante: da linguaggio dinamico “flessibile” a linguaggio sempre più strutturato, tipizzato e vicino ai linguaggi enterprise.
Grazie al miglioramento del sistema di tipi, che vedremo a breve, e l'introduzione di costrutti più espressivi ed un maggior rigore a runtime, oggi PHP non è più soltanto uno strumento per scrivere script web veloci, ma un linguaggio adatto a:
- applicazioni enterprise
- API complesse
- architetture a servizi
- sistemi modulabili e testabili
Quando scrissi il mio primo gestionale di magazzino, nel 2004, tutto questo sembrava lontano ma oggi è una bella realtà!
Gli strict types
Prendiamo questa funzione:
function sum(int $a, int $b): int {
return $a + $b;
}
echo sum("10", "20");
Stiamo passando dei valori numerici contenuti in variabili di tipo stringa ad una funzione matematica. Questa espressione fino a php8 ha funzionato senza problemi.
Se utilizziamo il nostro script con questa dichiarazione
declare(strict_types=1);
Viene generato un TypeError. E' unba bella caatteristica che migliora la qualità del codice, previene alcuni bug difficili da trovare in prima battuta e perfeziona il cosidetto "contratto" tra componenti.
In generale, è sempre bene dichiarare lo strict_types, almeno su progetti che iniziamo direttamente con php8.
Tipizzazione delle funzioni:
Php adesso permette, anzi raccomanda, di tipizzare sia i parametri in ingresso che i valori di ritorno:
function setAge(int $age): void {}
function setName(string $name): void {}
function setActive(bool $active): void {}
possiamo utilizzare anche tipi complessi come array o oggetti
function setUsers(array $users): void {}
function setUser(User $user): void {}
una bella novità è la possibilità di dichiarare più alternative:
function setCodice(int|string $code): void {
//ecc
}
quest'ultima opportunità però, chiamata "Union Types", va usata con parsimonia perchè ovviamente rende più complessa la fase di testing.
In linea di massima, tipizziamo tutto quello che riusciamo a tipizzare ma usiamo con molta parsimonia le dichiarazioni ambigue come mixed e gli union types.
Nullable Types
Possiamo dichiarare la possibilità di avere tipi null:
function setEmail(string|null $email): void {}
in questo modo ancora più diretto:
function setEmail(?string $email): void {}
Named Arguments
Un pò di "zucchero sintattico" per il nostro codice php:
function createUser(string $name, int $age, bool $active) {}
createUser(
name: "Mario",
age: 30,
active: true
);
L'ordine dei parametri non è più rilevante, il codice è più leggibile.. ma attenzione a non cambiare i nomi durante il refactoring!
Return Types avanzati
Non solo int, string, array.. ci sono altri tipi di ritorno a nostra disposizione: void, mixed e never!
function logAction(): void {}
function getValue(): mixed {
return "string";
}
function fail(string $message): never {
throw new Exception($message);
}
Vi starete chiedendo a che può servire una funzione "never", ovvero che non ritorna mai.. sono funzioni che terminano con un throw o un exit, usate durante fasi analitiche del codice.
Trovare errori prima dell'esecuzione
Grazie a PHPStan e Psalm, Php ci consente adesso di rilevare errori nel codice prima di lanciarlo in esecuzione, un pò come accade nei linguaggi compilati. Questi strumenti si occupano anche di verificare la coerenza tra i tipi e fornire consigli sull'architettura generale.