Menu

Namespace in PHP: namespace, use e alias

Un namespace PHP raggruppa classi, funzioni e costanti sotto un prefisso: namespace App\Models; in cima a un file, poi use App\Models\User; altrove per riferirsi alla classe con il nome breve. Impara i nomi completamente qualificati, gli alias con use ... as, use function, la barra rovesciata iniziale per le classi globali e l'autoloading PSR-4.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Un namespace PHP mette classi, funzioni e costanti sotto un prefisso così i loro nomi non possono entrare in conflitto con quelli di qualcun altro. Lo dichiari con namespace App\Models; come prima istruzione di un file, e gli altri file si riferiscono alla classe come \App\Models\User, oppure la importano con use App\Models\User; e scrivono solo User.

Dentro il namespace, User significa App\Models\User. User::class dà il nome completo come stringa senza creare nulla, comodo per il logging e per gli autoloader.

Due namespace in un file

Un progetto reale mette un namespace in ogni file. Per una demo autonoma, un file può contenerne diversi quando ciascuno è racchiuso tra graffe. Il codice che non appartiene a nessun namespace va in namespace { }:

Due classi chiamate Order vivono fianco a fianco perché i loro nomi completi sono diversi. È esattamente il problema che i namespace risolvono quando installi librerie: il tuo Order, l'Order di una libreria di pagamenti e l'Order di una libreria PDF non si scontrano più.

Importare con use e creare alias con as

Scrivere \Shop\Order ovunque è pesante. use in cima a un file (o a un blocco namespace) importa un nome così puoi usare la forma breve. Quando due import finirebbero con lo stesso nome breve, as dà a uno dei due un nome diverso:

use crea solo un nome breve per il resto del file. Non carica un file né esegue codice, e funziona allo stesso modo che la classe esista già o no. Sono consentiti anche gli import raggruppati: use Shop\{Order, Invoice};.

use function e use const

Le funzioni e le costanti di un namespace si importano con use function e use const:

Le classi globali richiedono una barra rovesciata

Dentro un namespace, un nome di classe non qualificato viene risolto rispetto a quel namespace, quindi new DateTime() dentro namespace App; cerca App\DateTime. Funzioni e costanti sono diverse: se App\strlen non esiste, PHP ripiega sullo strlen globale. Le classi non ripiegano mai.

Anche catch (\Error $e) richiedeva una barra rovesciata per lo stesso motivo: senza, PHP cercherebbe App\Error, non corrisponderebbe mai al vero errore, e lo script si fermerebbe con un Error non catturato. Risolvi con una barra rovesciata iniziale, come sopra, oppure con use DateTime; in cima al file. Lo stesso vale per \Exception, \Throwable e ogni altra classe predefinita; vedi try catch per catturarle.

Autoloading e PSR-4

In un progetto, ogni classe vive nel proprio file, e il percorso del file segue il namespace. PSR-4 è la convenzione: un prefisso di namespace corrisponde a una cartella di base, e il resto del nome diventa il percorso. Un autoloader registrato con spl_autoload_register() carica poi il file di una classe la prima volta che la classe viene usata. Questo blocco scrive su disco due file di classe e li carica automaticamente:

Ogni file di classe viene caricato una volta, nel momento in cui la classe serve per la prima volta. Nei progetti reali non scrivi tu questa funzione: Composer la genera da poche righe in composer.json:

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

Dopo composer dump-autoload, un solo require __DIR__ . '/vendor/autoload.php'; all'inizio dello script di ingresso carica su richiesta ogni classe App\....

Regole dei namespace che causano errori

  • namespace deve essere la prima istruzione del file. Possono precederlo solo declare(strict_types=1); e i commenti.
  • Gli import con use valgono per file. Importare una classe in index.php non fa funzionare il nome breve dentro un file incluso; ogni file ha bisogno delle proprie righe use.
  • use va al livello principale del file o del blocco namespace. Dentro il corpo di una classe, use significa un'altra cosa: include un trait.
  • Le stringhe non vengono mai risolte: $class = 'User'; new $class(); cerca lo User globale. Salva il nome completo, meglio se con User::class.

L'ultima merita una verifica veloce:

Domande frequenti

Cos'è un namespace in PHP?

Un prefisso che raggruppa classi, interfacce, funzioni e costanti correlate, come una cartella per i nomi. namespace App\Models; in cima a un file mette la sua classe User in App\Models\User, così non può entrare in conflitto con lo User di un'altra libreria.

Cosa fa use in PHP?

use App\Models\User; in cima a un file ti permette di scrivere User invece del nome completo \App\Models\User in quel file. Non carica né include nulla; caricare il file della classe è compito dell'autoloader. use ... as Alias; sceglie un nome breve diverso.

Perché ottengo Class not found dentro un namespace?

Dentro namespace App; un nome di classe semplice viene risolto rispetto al namespace, quindi new DateTime() cerca App\DateTime. Scrivi new \DateTime() oppure aggiungi use DateTime; in cima. Funzioni e costanti ripiegano automaticamente sul namespace globale, le classi no.

Cos'è la barra rovesciata prima di un nome di classe in PHP?

Una barra rovesciata iniziale rende il nome completamente qualificato, a partire dal namespace globale: \Exception è sempre l'Exception predefinita di PHP, in qualunque namespace si trovi il codice. Senza, il nome viene risolto rispetto al namespace corrente e agli import con use.

Che rapporto c'è tra namespace, cartelle e PSR-4?

PHP di per sé non lega i namespace alle cartelle. È PSR-4 la convenzione che lo fa: un prefisso come App\ corrisponde a una cartella come src/, quindi App\Models\User si trova in src/Models/User.php. L'autoloader di Composer la segue, ed è per questo che di solito i due coincidono.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA