Namespaces são uma funcionalidade essencial do PHP para organizar classes, interfaces, funções e constantes em grupos lógicos, evitando conflitos de nomes entre diferentes partes de um projeto ou bibliotecas de terceiros. Introduzidos no PHP 5.3, os namespaces permitem que você crie código mais modular e reutilizável, especialmente em projetos grandes ou ao integrar múltiplos pacotes.

Nesta aula, exploraremos como declarar namespaces, como importar símbolos usando a palavra-chave use, como criar aliases para nomes longos e como organizar seu código de forma eficiente. Vamos usar exemplos práticos para cada conceito.

namespace

Um namespace é um contêiner abstrato que agrupa itens relacionados. A declaração de namespace deve ser a primeira instrução no arquivo PHP (antes de qualquer código não namespace, exceto declare). A sintaxe é namespace NomeDoNamespace;. Você pode usar subnamespaces separando por barra invertida (\), como App\Model.

Quando você define uma classe dentro de um namespace, ela é referenciada pelo nome completo (fully qualified name) que inclui o namespace. Por exemplo, App\Model\User. Isso evita colisões se outro pacote também tiver uma classe User.

<?php
namespace App\Model;

class User {
    public function greet() {
        return "Olá do namespace App\\Model!";
    }
}
?>

Para usar essa classe fora do namespace, você precisa referenciá-la pelo nome completo: $user = new \App\Model\User();. O namespace global (sem nome) é acessado prefixando com uma barra invertida, como \DateTime.

use

A palavra-chave use permite importar um namespace ou classe para o escopo atual, evitando escrever o nome completo toda vez. A importação é feita no topo do arquivo, após a declaração de namespace (se houver). Você pode importar classes, interfaces, funções e constantes.

Exemplo de importação de classe: use App\Model\User;. Depois disso, você pode usar apenas User no código. Para funções e constantes, use use function e use const respectivamente.

<?php
namespace App\Controller;

use App\Model\User;
use function App\Utils\formatDate;
use const App\Config\MAX_ITEMS;

class UserController {
    public function show() {
        $user = new User(); // Resolve para App\Model\User
        echo formatDate(time());
        echo MAX_ITEMS;
    }
}
?>

É possível importar múltiplos itens separando por vírgula: use App\Model\User, App\Model\Admin;. Mas a prática recomendada é usar uma declaração por linha para melhor legibilidade.

Aliases

Aliases permitem renomear um nome importado para evitar conflitos ou encurtar nomes muito longos. A sintaxe é use NomeOriginal as Alias;. Você pode criar aliases para classes, funções e constantes.

Por exemplo, se você está usando duas bibliotecas que têm uma classe Logger, pode criar aliases diferentes:

<?php
use MyFramework\Logger as FrameworkLogger;
use ThirdParty\Logger as ThirdPartyLogger;

$logger1 = new FrameworkLogger();
$logger2 = new ThirdPartyLogger();
?>

Aliases também são úteis para encurtar nomes de classes muito longos, como use Very\Long\Namespace\ClassName as Short;. Lembre-se que o alias é válido apenas no escopo do arquivo onde é declarado.

Organização de código

Para organizar projetos PHP com namespaces, siga a convenção PSR-4, que mapeia namespaces para diretórios. Por exemplo, o namespace App\Model corresponde ao diretório src/Model. Cada classe fica em seu próprio arquivo com o mesmo nome da classe. Isso facilita o autoloading.

Exemplo de estrutura de diretórios:

projeto/
├── src/
│   ├── Model/
│   │   └── User.php
│   ├── Controller/
│   │   └── UserController.php
│   └── Utils/
│       └── Validator.php
├── public/
│   └── index.php
└── composer.json

No arquivo User.php, o namespace é App\Model. O autoloader (como o do Composer) carrega a classe automaticamente quando ela é usada. Para configurar o Composer, adicione no composer.json:

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

Depois, execute composer dump-autoload. Agora, no index.php, você pode usar:

<?php
require_once 'vendor/autoload.php';

use App\Model\User;
use App\Controller\UserController;

$user = new User();
echo $user->greet();
?>

Essa organização mantém o código limpo, modular e fácil de manter.

Boas práticas

  • Use namespaces consistentes com a estrutura de diretórios (PSR-4).
  • Evite importar múltiplas classes com aliases desnecessários; use apenas quando houver conflito.
  • Prefira importar classes individualmente em vez de usar use com curinga (não suportado em PHP).
  • Nunca declare namespaces em arquivos que contenham código procedural misturado; separe bem.

Referências

Exercícios

  1. Crie um namespace App\Utils com uma função formatDate que retorna a data atual formatada como 'd/m/Y'. Em seguida, importe e use essa função em um arquivo separado.

    ✓ Resposta:
    // src/Utils/helpers.php
    <?php
    namespace App\Utils;
    
    function formatDate($timestamp = null) {
        $timestamp = $timestamp ?? time();
        return date('d/m/Y', $timestamp);
    }
    ?>
    
    // index.php
    <?php
    require_once 'src/Utils/helpers.php';
    
    use function App\Utils\formatDate;
    
    echo formatDate(); // Exemplo: 15/03/2025
    ?>
  2. Importe a classe DateTime do namespace global e crie um alias DT. Instancie e exiba a data atual.

    ✓ Resposta:
    <?php
    use DateTime as DT;
    
    $dt = new DT();
    echo $dt->format('Y-m-d H:i:s');
    ?>
  3. Declare duas classes com o mesmo nome Logger em namespaces diferentes: App\Log e Vendor\Log. No código principal, importe ambas usando aliases e instancie cada uma.

    ✓ Resposta:
    // src/Log/Logger.php
    <?php
    namespace App\Log;
    
    class Logger {
        public function log($msg) {
            echo "App Log: $msg\n";
        }
    }
    ?>
    
    // vendor/Vendor/Log/Logger.php
    <?php
    namespace Vendor\Log;
    
    class Logger {
        public function log($msg) {
            echo "Vendor Log: $msg\n";
        }
    }
    ?>
    
    // index.php
    <?php
    require_once 'src/Log/Logger.php';
    require_once 'vendor/Vendor/Log/Logger.php';
    
    use App\Log\Logger as AppLogger;
    use Vendor\Log\Logger as VendorLogger;
    
    $appLogger = new AppLogger();
    $vendorLogger = new VendorLogger();
    $appLogger->log('teste');
    $vendorLogger->log('teste');
    ?>
  4. Organize as seguintes classes em namespaces seguindo PSR-4: User (model), UserController (controller). Crie a estrutura de diretórios e o autoload com Composer. Escreva o código de exemplo que instancia um User.

    ✓ Resposta:
    projeto/
    ├── src/
    │   ├── Model/
    │   │   └── User.php
    │   └── Controller/
    │       └── UserController.php
    ├── public/
    │   └── index.php
    └── composer.json
    // src/Model/User.php
    <?php
    namespace App\Model;
    
    class User {
        public function getName() {
            return "João";
        }
    }
    ?>
    
    // src/Controller/UserController.php
    <?php
    namespace App\Controller;
    
    use App\Model\User;
    
    class UserController {
        public function show() {
            $user = new User();
            return $user->getName();
        }
    }
    ?>
    
    // composer.json
    {
        "autoload": {
            "psr-4": {
                "App\\": "src/"
            }
        }
    }
    
    // public/index.php
    <?php
    require_once '../vendor/autoload.php';
    
    use App\Model\User;
    
    $user = new User();
    echo $user->getName();
    ?>
  5. Crie um namespace App\Config com uma constante MAX_ITEMS igual a 50. Importe-a em outro arquivo usando use const e exiba seu valor.

    ✓ Resposta:
    // src/Config/constants.php
    <?php
    namespace App\Config;
    
    define('App\Config\MAX_ITEMS', 50);
    // Ou use const:
    const MAX_ITEMS = 50;
    ?>
    
    // index.php
    <?php
    require_once 'src/Config/constants.php';
    
    use const App\Config\MAX_ITEMS;
    
    echo MAX_ITEMS; // 50
    ?>