f in x
Intersection e Union Types in PHP 8 — Tipo Sicurezza Senza Compromessi per Codice Che Non Si Rompe a Runtime
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sviluppo di siti web

Intersection e Union Types in PHP 8 — Tipo Sicurezza Senza Compromessi per Codice Che Non Si Rompe a Runtime

[2026-07-11] Author: Ing. Calogero Bono
Zenithby Meteora Web Il sistema operativo della tua attività. Social, clienti, prenotazioni e fatture in un'unica piattaforma. Palestre, barber, professionisti. Scopri Zenith Demo gratis · senza carta

Se hai mai scritto @param int|string $id nei PHPDoc, hai già incontrato le union types. Ma PHP 8 le rende native, eliminando ogni ambiguità. E con PHP 8.1 arriva anche il contrario: le intersection types. Noi di Meteora Web lavoriamo su codebase PHP da oltre 8 anni — abbiamo visto progetti interi basati su docblock e controlli manuali che avrebbero potuto essere risolti con due caratteri ben piazzati. Questa guida ti porta nel cuore del type system di PHP 8, senza fronzoli, con codice che puoi copiare oggi.

Cosa sono le Union Types e perché usarle?

Una union type dichiara che un valore può essere uno tra più tipi. In PHP 7.4 potevi già usare ?int per int|null, ma per combinazioni diverse dovevi affidarti ai commenti. Con PHP 8.0 scrivi direttamente:

public function find(int|string $id): ?User { ... }

Il vantaggio è immediato: l’interprete verifica il tipo a runtime e un IDE moderno (PhpStorm, VS Code con intelephense) capisce esattamente cosa aspettarsi. Niente più “mixed” vaghi o controlli a cascata. Se la tua funzione accetta un ID numerico o uno slug testuale, union type è la strada giusta.

Sponsored Protocol

Dichiarazione di return con union

function fetchCustomer(int|string $identifier): Customer|false { ... }

Qui false è un tipo scala valido (tipico pattern di funzioni built-in). In un progetto reale, preferiamo sempre restituire null invece di false — ma se lavori con codice legacy, la union Customer|false è già un passo avanti rispetto a mixed.

Come si usano le Intersection Types in PHP 8.1?

Le intersection types (introdotte in PHP 8.1) rappresentano l’esatto opposto: un valore deve soddisfare tutti i tipi contemporaneamente. Si scrivono con il & e funzionano solo con tipi oggetto (classi, interfacce, trait).

interface Renderable {
    public function render(): string;
}
interface Loggable {
    public function log(string $message): void;
}

function process(Renderable&Loggable $entity): void {
    echo $entity->render();
    $entity->log('processed');
}

La funzione process accetta solo oggetti che implementano entrambe le interfacce. Se passi un oggetto che implementa solo Renderable, PHP lancia un TypeError a runtime. Le intersection types sono perfette per combinare contratti senza ereditarietà multipla — molto più pulito di classi astratte piene di instanceof.

Sponsored Protocol

Quali differenze tra Union e Intersection Types?

La differenza è logica:

  • Union (|): “A o B” – almeno uno dei tipi deve essere soddisfatto.
  • Intersection (&): “A e B” – tutti i tipi devono essere soddisfatti contemporaneamente.

Le union si applicano a qualsiasi tipo (scalari, oggetti, null). Le intersection funzionano solo su tipi oggetto perché un valore non può essere contemporaneamente un intero e una stringa. Inoltre, l’intersezione tra due classi che non condividono gerarchia è impossibile a livello logico — PHP lo segnala come errore in fase di compilazione del codice.

Come gestire il tipo null con le Union Types?

PHP 8 ha reso ?Type un alias di Type|null. Puoi scrivere indifferentemente:

Sponsored Protocol

public function getTitle(): ?string { ... }
// Equivalente:
public function getTitle(): string|null { ... }

Noi consigliamo di usare ?Type quando è una singola unione con null, e Type1|Type2|null quando la combinazione è più complessa. La leggibilità conta.

Esempi pratici di Union e Intersection Types in un progetto reale

Caso 1: Repository generico con identificatori multipli

interface EntityRepository
{
    public function find(int|string $id): ?Entity;
    public function findByCriteria(string $field, int|string|float $value): array;
}

In una nostra piattaforma clienti (Laravel/Livewire) gestiamo utenti con ID numerico o UUID. Una sola interfaccia copre entrambi i casi, senza duplicare metodi.

Caso 2: Validatore con intersezione di interfacce

interface Validatable {
    public function validate(): bool;
}
interface Persistable {
    public function save(): void;
}

function saveIfValid(Validatable&Persistable $entity): void {
    if ($entity->validate()) {
        $entity->save();
    }
}

Il metodo saveIfValid accetta solo entità che possono essere validate e salvate. Se domani un oggetto implementa solo Validatable, il compilatore lo blocca subito, non a runtime dopo ore di test.

Sponsored Protocol

Caso 3: Risposta API con errore

function apiResponse(): array{status: string, data?: array|string}

Non è una vera union type su una proprietà, ma in una struttura associativa puoi usare i tipi in modo simile. Per una vera sicurezza, meglio creare un DTO tipizzato.

Errori comuni da evitare con i tipi composti in PHP 8

  • Intersezione con un tipo scalare: string&int non ha senso — PHP dà errore in fase di compilazione (Parse error). Ricorda: solo tipi oggetto.
  • Unioni ridondanti: int|string|int è valida ma inutile. PHP non duplica i tipi, ma pulisci il codice.
  • Dimenticare null esplicito: Se una funzione può restituire null, dichiaralo sempre. ?string o string|null, mai solo string se c’è il caso.
  • Confondere | con &: leggendo velocemente, uno slash può ingannare. Noi mettiamo sempre spazi tra i tipi: int | string (PHP accetta spazi).

Cosa fare adesso

  1. Rivedi le firme delle tue funzioni che usano mixed o @param nei docblock. Converti in union types dove i casi possibili sono noti (max 2-3 tipi).
  2. Crea un’interfaccia marker se hai bisogno di intersection types: ad esempio Exportable e Printable, e usa Exportable&Printable nei punti che richiedono entrambi.
  3. Aggiorna il phpstan/psalm al livello massimo: i tipi nativi riducono i falsi positivi degli analyzer statici e rendono il codice auto-documentante.
  4. Leggi la documentazione ufficiale PHP per i dettagli sulle regole di covarianza/contravarianza: PHP Type Declarations.
  5. Se usi Laravel, sfrutta le union nei form request personalizzati e nei repository. Noi abbiamo scritto una guida più estesa nel nostro Pillar PHP 8 Avanzato — include anche performance e async.

I tipi non sono burocrazia. Sono contratti che il compilatore fa rispettare gratis. Iniziare oggi con union e intersection ti fa risparmiare ore di debugging domani.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere informatico, fondatore di Meteora Web e Zenith OS. System administrator e progettista di piattaforme, app e CMS proprietari, con esperienza in sviluppo full-stack, marketing digitale ed ecosistema Google.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()