Namespaces: organizando o código
1. O que são namespaces e por que usá-los?
Namespaces no PHP são uma forma de encapsular itens como classes, funções e constantes, evitando conflitos de nomes entre diferentes bibliotecas ou partes de uma aplicação. Imagine que você está desenvolvendo um sistema de e-commerce e precisa usar uma biblioteca de terceiros chamada "Pagamento" que possui uma classe Cartao. Simultaneamente, seu próprio código também define uma classe Cartao. Sem namespaces, haveria um conflito fatal.
A analogia mais comum é com diretórios em um sistema de arquivos: você pode ter dois arquivos chamados index.html em pastas diferentes (/admin/index.html e /site/index.html). Da mesma forma, namespaces permitem que duas classes tenham o mesmo nome, desde que estejam em namespaces diferentes (App\Pagamento\Cartao e Biblioteca\Pagamento\Cartao).
Além de evitar colisões, namespaces organizam logicamente o código, tornando-o mais legível e facilitando a manutenção. Eles são fundamentais para projetos modernos em PHP, especialmente quando combinados com autoloading.
2. Declarando e importando namespaces
A declaração de um namespace é feita com a palavra-chave namespace no início do arquivo, antes de qualquer outro código (exceto declare). A sintaxe é simples:
<?php
namespace App\Pagamento;
class Cartao {
public function processar() {
return "Processando pagamento com cartão";
}
}
Você pode declarar múltiplos namespaces em um mesmo arquivo, embora isso seja raro e geralmente desencorajado:
<?php
namespace App\Pagamento {
class Boleto {
// ...
}
}
namespace App\Frete {
class Correios {
// ...
}
}
Para importar um namespace, usamos use. O alias com as permite renomear temporariamente:
<?php
use App\Pagamento\Cartao as CartaoPagamento;
use App\Pagamento\Boleto;
use function App\Helpers\formatarMoeda;
use const App\Config\TAXA_JUROS;
$cartao = new CartaoPagamento();
$boleto = new Boleto();
echo formatarMoeda(150.00);
echo TAXA_JUROS;
A partir do PHP 7, você pode agrupar imports:
use App\Pagamento\{Cartao, Boleto};
use function App\Helpers\{formatarMoeda, calcularDesconto};
3. Hierarquia e sub-namespaces
Os namespaces podem ser hierárquicos, usando a barra invertida (\) como separador. Isso permite criar uma estrutura lógica que reflete a arquitetura da aplicação:
<?php
namespace App\Models;
class User {
public function getNome() {
return "João";
}
}
<?php
namespace App\Controllers;
use App\Models\User;
class UserController {
public function mostrar() {
$user = new User();
return $user->getNome();
}
}
A relação entre namespaces e diretórios é padronizada pelo PSR-4 (uma recomendação do PHP-FIG). Se você tem uma classe App\Models\User, ela deve estar no arquivo src/Models/User.php. O namespace raiz App mapeia para o diretório src/:
projeto/
├── src/
│ ├── Models/
│ │ └── User.php
│ └── Controllers/
│ └── UserController.php
└── composer.json
4. Resolução de nomes: fully qualified vs. relative
No PHP, existem três tipos de resolução de nomes:
Nomes fully qualified (absolutos): começam com \ e referenciam diretamente o namespace raiz:
$user = new \App\Models\User(); // Absoluto, funciona de qualquer lugar
Nomes relativos: não começam com \ e são resolvidos a partir do namespace atual:
<?php
namespace App\Controllers;
use App\Models\User;
class UserController {
public function teste() {
// Resolve para App\Controllers\OutraClasse (se existir)
$outra = new OutraClasse();
// Com use, resolve para App\Models\User
$user = new User();
}
}
Comportamento do use: a declaração use App\Models\User cria um alias local, permitindo usar apenas User no arquivo. Se você não usar use, precisará do nome completo ou absoluto.
5. Namespaces e autoloading com Composer
O verdadeiro poder dos namespaces aparece quando combinados com autoloading via Composer. Configure o composer.json com PSR-4:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Depois, execute composer dump-autoload. Agora, qualquer classe no namespace App\Services será automaticamente carregada do diretório src/Services/:
<?php
// src/Services/PagamentoService.php
namespace App\Services;
class PagamentoService {
public function executar() {
return "Serviço de pagamento executado";
}
}
<?php
// index.php
require 'vendor/autoload.php';
use App\Services\PagamentoService;
$servico = new PagamentoService();
echo $servico->executar();
O Composer cuida de incluir o arquivo correto automaticamente quando você instancia a classe, eliminando a necessidade de require ou include manuais.
6. Boas práticas e armadilhas comuns
Convenção de nomenclatura: use PascalCase para namespaces e classes. Exemplo: App\Services\RelatorioService.
Evite aliases excessivos: usar use App\AlgumNome\Muito\Grande\Classe as C pode tornar o código confuso. Prefira nomes descritivos.
Cuidado com use function e use const: a partir do PHP 5.6, você pode importar funções e constantes:
use function array_map;
use const PHP_VERSION;
Isso evita ambiguidades, mas use com moderação para não poluir o escopo.
Escopo de namespaces: lembre-se que namespace deve ser a primeira declaração no arquivo. Um erro comum é colocar código antes dela:
<?php
echo "Olá"; // Erro! Nada pode vir antes de namespace
namespace App;
7. Casos avançados: namespaces dinâmicos e global
Constante mágica __NAMESPACE__: retorna o namespace atual como string:
<?php
namespace App\Helpers;
echo __NAMESPACE__; // App\Helpers
Isso é útil para criar dinamicamente nomes de classes:
$classe = __NAMESPACE__ . '\\' . 'Formatador';
$obj = new $classe();
Namespace global: classes sem namespace (como Exception, DateTime) estão no namespace global. Para acessá-las dentro de um namespace, use \Exception:
<?php
namespace App;
try {
// ...
} catch (\Exception $e) {
echo $e->getMessage();
}
Namespaces em arquivos de bootstrap: é comum usar namespaces em arquivos de configuração:
<?php
// bootstrap.php
namespace App\Config;
const DB_HOST = 'localhost';
const DB_NAME = 'meubanco';
function conectar() {
// ...
}
Depois, importe com use const App\Config\DB_HOST e use function App\Config\conectar.
Referências
- PHP Manual: Namespaces — Documentação oficial completa sobre namespaces no PHP, incluindo sintaxe, importação e resolução de nomes.
- PSR-4: Autoloading Standard — Especificação oficial do PHP-FIG que define como mapear namespaces para diretórios no autoloading.
- Composer: Autoloading — Guia oficial do Composer sobre configuração de autoloading com PSR-4 e outras estratégias.
- PHP The Right Way: Namespaces — Artigo prático que explica namespaces de forma acessível, com exemplos reais e boas práticas.
- Stack Overflow: PHP Namespace Basics — Discussão técnica com exemplos práticos sobre declaração, importação e resolução de nomes em namespaces.