Um namespace PHP coloca classes, funções e constantes sob um prefixo para que os nomes delas não colidam com os de mais ninguém. Você o declara com namespace App\Models; como primeira instrução de um arquivo, e outros arquivos se referem à classe como \App\Models\User, ou a importam com use App\Models\User; e escrevem só User.
Dentro do namespace, User significa App\Models\User. User::class dá o nome completo como string sem criar nada, o que é prático para logs e autoloaders.
Dois namespaces num arquivo
Um projeto real coloca um namespace em cada arquivo. Para uma demonstração autocontida, um arquivo pode ter vários namespaces quando cada um fica entre chaves. Código que não pertence a nenhum namespace vai em namespace { }:
Duas classes chamadas Order vivem lado a lado porque os nomes completos são diferentes. É exatamente o problema que os namespaces resolvem quando você instala bibliotecas: o seu Order, o Order de uma biblioteca de pagamentos e o Order de uma biblioteca de PDF não colidem mais.
Importar com use e criar alias com as
Escrever \Shop\Order em todo lugar polui o código. use no topo de um arquivo (ou de um bloco de namespace) importa um nome para você usar a forma curta. Quando dois imports terminariam no mesmo nome curto, as dá a um deles outro nome:
use só cria um nome curto para o resto do arquivo. Ele não carrega um arquivo nem executa código, e funciona do mesmo jeito exista a classe ou não. Imports agrupados também são permitidos: use Shop\{Order, Invoice};.
use function e use const
Funções e constantes num namespace são importadas com use function e use const:
Classes globais precisam de barra invertida
Dentro de um namespace, um nome de classe sem qualificação é resolvido em relação àquele namespace, então new DateTime() dentro de namespace App; procura App\DateTime. Funções e constantes são diferentes: se App\strlen não existe, o PHP cai no strlen global. Classes nunca caem.
O catch (\Error $e) precisou de barra invertida pelo mesmo motivo: sem ela o PHP procuraria App\Error, nunca bateria com o erro real, e o script pararia com um Error não capturado. Corrija com uma barra invertida inicial, como acima, ou com use DateTime; no topo do arquivo. O mesmo vale para \Exception, \Throwable e todas as outras classes nativas; veja try catch para capturá-las.
Autoload e PSR-4
Num projeto, cada classe fica no próprio arquivo, e o caminho do arquivo segue o namespace. O PSR-4 é a convenção: um prefixo de namespace corresponde a uma pasta base, e o resto do nome vira o caminho. Um autoloader registrado com spl_autoload_register() então carrega o arquivo de uma classe na primeira vez que ela é usada. Este bloco escreve dois arquivos de classe no disco e os carrega com autoload:
Cada arquivo de classe é carregado uma vez, no momento em que a classe é necessária pela primeira vez. Em projetos reais você não escreve essa função: o Composer a gera a partir de algumas linhas no composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Depois de composer dump-autoload, um único require __DIR__ . '/vendor/autoload.php'; no início do seu script de entrada carrega sob demanda todas as classes App\....
Regras de namespace que causam erros
namespaceprecisa ser a primeira instrução do arquivo. Sódeclare(strict_types=1);e comentários podem vir antes.- Imports com
usevalem por arquivo. Importar uma classe emindex.phpnão faz o nome curto funcionar dentro de um arquivo incluído; cada arquivo precisa das próprias linhasuse. usefica no nível superior do arquivo ou do bloco de namespace. Dentro do corpo de uma classe,usesignifica outra coisa: ele incorpora uma trait.- Strings nunca são resolvidas:
$class = 'User'; new $class();procura oUserglobal. Guarde o nome completo, de preferência comUser::class.
A última merece uma verificação rápida:
Perguntas frequentes
O que é um namespace no PHP?
Um prefixo que agrupa classes, interfaces, funções e constantes relacionadas, como uma pasta para nomes. namespace App\Models; no topo de um arquivo coloca a classe User dele em App\Models\User, então ela não colide com o User de outra biblioteca.
O que faz o use no PHP?
use App\Models\User; no topo de um arquivo deixa você escrever User em vez do nome completo \App\Models\User naquele arquivo. Ele não carrega nem inclui nada; carregar o arquivo da classe é trabalho do autoloader. use ... as Alias; escolhe outro nome curto.
Por que recebo Class not found dentro de um namespace?
Dentro de namespace App;, um nome de classe sem prefixo é resolvido em relação ao namespace, então new DateTime() procura App\DateTime. Escreva new \DateTime() ou adicione use DateTime; no topo. Funções e constantes caem no namespace global automaticamente, classes não.
O que é a barra invertida antes de um nome de classe no PHP?
Uma barra invertida inicial torna o nome totalmente qualificado, a partir do namespace global: \Exception é sempre o Exception nativo do PHP, em qualquer namespace em que o código esteja. Sem ela, o nome é resolvido em relação ao namespace atual e aos imports com use.
Qual a relação entre namespaces, pastas e PSR-4?
O PHP em si não liga namespaces a pastas. O PSR-4 é a convenção que faz isso: um prefixo como App\ corresponde a um diretório como src/, então App\Models\User fica em src/Models/User.php. O autoloader do Composer segue essa convenção, e é por isso que os dois normalmente batem.