Médio PHP

Autoload PSR-4 manual

Enunciado

Implemente um autoloader que siga o padrão PSR-4 para o prefixo App\ mapeado para o diretório src/. Crie as classes App\Models\User (com getName()) e App\Services\UserService (com greet(User $user) retornando "Olá, " . $user->getName()). O autoloader deve carregar automaticamente os arquivos quando as classes forem usadas. No arquivo principal, registre o autoloader, instancie as classes e exiba a saudação.

Requisitos

  • O autoloader verifica se o prefixo App\ corresponde ao início do nome da classe.
  • Converte o namespace para caminho de arquivo: src/Models/User.php.
  • Inclui o arquivo apenas se ele existir.
  • O programa principal usa as classes sem require manual.

Código inicial

<?php
// Implemente o autoloader PSR-4 e as classes

Saída esperada

Olá, Maria
Ver dica

Use spl_autoload_register, str_replace para trocar \ por / e file_exists antes de incluir.

Mostrar solução
<?php
// autoload.php
spl_autoload_register(function ($class) {
    $prefix = 'App\\';
    $baseDir = __DIR__ . '/src/';

    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        return;
    }

    $relativeClass = substr($class, $len);
    $file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';

    if (file_exists($file)) {
        require $file;
    }
});
<?php
// src/Models/User.php
namespace App\Models;

class User
{
    public function __construct(private string $name) {}

    public function getName(): string
    {
        return $this->name;
    }
}
<?php
// src/Services/UserService.php
namespace App\Services;

use App\Models\User;

class UserService
{
    public function greet(User $user): string
    {
        return 'Olá, ' . $user->getName();
    }
}
<?php
// index.php
require 'autoload.php';

use App\Models\User;
use App\Services\UserService;

$user = new User('Maria');
$service = new UserService();
echo $service->greet($user);

Passo a passo

  1. No autoload.php, registramos uma função anônima com spl_autoload_register.
  2. A função recebe o nome completo da classe (ex.: App\Models\User).
  3. Verificamos se o prefixo App\ está no início do nome; se não, retornamos.
  4. Extraímos a parte relativa (Models\User).
  5. Substituímos \ por / e montamos o caminho src/Models/User.php.
  6. Se o arquivo existir, incluímos com require.
  7. No index.php, incluímos o autoloader e usamos as classes normalmente.

Por que funciona

O autoloader é chamado automaticamente pelo PHP quando uma classe não é encontrada. Seguindo PSR-4, o namespace reflete a estrutura de diretórios, então o arquivo correto é carregado sob demanda.

Erros comuns

  • Não verificar o prefixo: o autoloader tenta carregar classes de outros namespaces e pode incluir arquivos errados.
  • Esquecer a barra invertida no prefixo: $prefix = 'App\'; (com uma barra) é inválido; use 'App\\' ou 'App\\' em strings.
  • Caminho base sem __DIR__: usar caminho relativo pode falhar dependendo do diretório de trabalho.

Outra forma de resolver

Com Composer, basta configurar o composer.json e rodar composer dump-autoload. O autoloader gerado é mais robusto e otimizado.

Saída esperada

Olá, Maria