Situação atual: PHP2Shell. Duas vulnerabilidades críticas do PHP (CVSS 9,2) permitem executar código malicioso sem autenticação. Patches disponíveis desde 21/10/2026.O que fazer agora →

Espaços de nomes e autoloading (PSR-4)

Os espaços de nomes organizam o código PHP, o autoloading carrega as classes exatamente quando são precisas. Aqui vê como o PSR-4 mapeia nomes de classe para ficheiros e por que razão o autoloader deve ser verificado após um incidente.

Atualizado em 5 min de leituraConhecimento PHP

Em resumo: Os espaços de nomes são, em PHP, algo como pastas para nomes de classes: App\Rechnung\Pdf e Bibliothek\Pdf podem coexistir sem se perturbarem. O autoloading faz com que o PHP só carregue uma classe quando ela é usada pela primeira vez. O padrão PSR-4 define como um nome de classe passa a caminho de ficheiro; o Composer gera depois o autoloader adequado. Como este autoloader corre em cada pedido, é uma das primeiras coisas a verificar após um incidente de segurança.

Porque é que o PHP precisa de espaços de nomes

Os espaços de nomes existem desde o PHP 5.3.0. Antes, todas as classes e funções partilhavam um único espaço de nomes global. Se duas bibliotecas se chamassem Logger, havia um colapso. Os programadores arranjavam-se com nomes longos como Firma_Modul_Unterbereich_Logger.

O manual do PHP indica dois problemas que os espaços de nomes resolvem: colisões de nomes entre código próprio, classes internas do PHP e bibliotecas de terceiros, e nomes demasiado longos que surgiram apenas para contornar essas colisões. Para quem decide, isto significa: só com os espaços de nomes se tornou praticável combinar dezenas de pacotes alheios num projeto, como hoje é habitual com o Composer.

Espaços de nomes na prática: namespace, use, aliases

Um ficheiro declara o seu espaço de nomes na primeira instrução. Com use trazem-se classes de outros espaços de nomes, se desejado com um nome mais curto.

<?php
declare(strict_types=1);

namespace App\Rechnung;

use App\Kunde\Kunde;
use Psr\Log\LoggerInterface as Log;

final class PdfErzeuger
{
    public function __construct(private Log $log) {}

    public function erzeugen(Kunde $kunde): string
    {
        $this->log->info('PDF erzeugt', ['kunde' => $kunde->id]);
        return \sprintf('Rechnung für %s', $kunde->name);
    }
}

O nome completo desta classe é App\Rechnung\PdfErzeuger. A barra invertida inicial em \sprintf remete expressamente para a função global do PHP.

Autoloading: carregar classes quando necessário

Sem autoloading, cada script teria de incluir com require todos os ficheiros de que precisa. Com spl_autoload_register() regista-se, em vez disso, uma função que o PHP chama assim que é usada uma classe, interface, trait ou enum desconhecidos. Recebe o nome da classe e carrega o ficheiro correspondente.

<?php
spl_autoload_register(function (string $klasse): void {
    $praefix = 'App\\';
    $basis   = __DIR__ . '/src/';

    if (!str_starts_with($klasse, $praefix)) {
        return; // não é da sua competência, a vez é do autoloader seguinte
    }
    $datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
    if (is_file($datei)) {
        require $datei;
    }
});

O spl_autoload_register() pode ser chamado várias vezes. O PHP consulta então os autoloaders registados um a seguir ao outro, até que um tenha carregado a classe. Na prática, as aplicações grandes têm muitas vezes vários: o autoloader do Composer para as bibliotecas, um próprio do CMS e outros de plugins ou módulos. Para os administradores, isto significa: o código que é realmente carregado num pedido resulta da interação de todos estes autoloaders e não apenas da estrutura de pastas.

O manual desaconselha vivamente lançar exceções num autoloader; o PSR-4 proíbe-o expressamente. A função mais antiga __autoload() foi marcada como obsoleta no PHP 7.2.0 e removida no PHP 8.0.0.

PSR-4: do nome da classe ao caminho do ficheiro

O PSR-4 é um padrão da PHP-FIG. Um nome de classe completo começa com um espaço de nomes do fabricante. Um prefixo do espaço de nomes é associado a um diretório base, o resto do nome dá as subpastas e o ficheiro termina em .php. A distinção entre maiúsculas e minúsculas tem de coincidir exatamente. Assim se vê a associação no composer.json:

{
    "autoload": {
        "psr-4": { "App\\": "src/" }
    }
}
Nome da classe Ficheiro
App\Kunde\Kunde src/Kunde/Kunde.php
App\Rechnung\PdfErzeuger src/Rechnung/PdfErzeuger.php
App\Rechnung\Pdf\Vorlage src/Rechnung/Pdf/Vorlage.php

Um obstáculo clássico é a distinção entre maiúsculas e minúsculas. Em computadores de desenvolvimento com Windows ou macOS, o sistema de ficheiros muitas vezes não distingue entre Kunde.php e kunde.php, mas num servidor Linux distingue. Uma aplicação que corre localmente não encontra então uma classe no servidor. A regra do PSR-4 de usar os nomes exatamente na grafia correta evita estas surpresas na entrega.

Além de psr-4, o Composer conhece classmap, para código sem estrutura padrão, e files, para ficheiros carregados em todos os pedidos, por exemplo funções auxiliares. Outros padrões da PHP-FIG são descritos na página Padrões PSR.

Otimizar o autoloader em produção

Em produção, o ideal é que o autoloader já não procure no sistema de ficheiros, mas consulte uma lista pronta. O Composer oferece para isso dois níveis:

  1. composer install --no-dev --optimize-autoloader converte as regras PSR-4 numa lista de classes. Segundo a documentação do Composer, é recomendado para produção.
  2. --classmap-authoritative vai mais longe: as classes são carregadas exclusivamente a partir da lista. Os ficheiros que nela não constem, o autoloader nem sequer os carrega.
  3. A cada entrega, a lista é gerada de novo, para que as classes novas sejam encontradas.

Autoloading e segurança após o PHP2Shell

O PHP2Shell diz respeito ao interpretador PHP, não ao autoloader. Continuam obrigatórios a atualização para o PHP 8.5.12, 8.4.27, 8.3.36 ou 8.2.35 e o reinício de todos os workers. Após um possível incidente, o autoloader merece, porém, atenção especial: o vendor/autoload.php e todos os ficheiros registados em files são executados a cada pedido. Uma linha aí introduzida atua, portanto, em todo o site, sem que haja um ficheiro novo e chamativo na pasta de uploads.

Verifique por isso se o vendor e os ficheiros de autoload correspondem ao estado verificado do controlo de versões. São úteis os artigos Encontrar ficheiros alterados recentemente e Comparar os ficheiros do núcleo do CMS com o original. Em caso de dúvida, um vendor gerado de novo a partir do ficheiro lock é mais seguro do que qualquer reparação isolada.

Como ajuda concretamente a PHP SOS?

  • Comparamos o vendor, o autoloader e os ficheiros de entrada com o estado verificado e assinalamos qualquer desvio.
  • Restabelecemos o conjunto de pacotes a partir do ficheiro lock e configuramos um autoloader otimizado.
  • Verificamos se apenas a pasta pública está na raiz web e se o código-fonte não é diretamente acessível por URL.
  • Em caso de infeção, assumimos a limpeza no âmbito da remoção de malware e documentamos o resultado.

Perguntas frequentes

Desde quando existem espaços de nomes no PHP?

Desde o PHP 5.3.0. Segundo o manual, resolvem dois problemas: colisões de nomes entre código próprio, o PHP e bibliotecas de terceiros, e nomes de classe demasiado longos que só surgiram para evitar essas colisões.

Qual é a diferença entre PSR-0 e PSR-4?

Ambos mapeiam nomes de classe para caminhos de ficheiro. No PSR-4, o prefixo do espaço de nomes não se repete no caminho do ficheiro, o que dá diretórios mais planos. O PSR-0 está classificado como obsoleto pela PHP-FIG; o PSR-4 é o padrão recomendado.

O __autoload() ainda funciona?

Não. O __autoload() foi marcado como obsoleto no PHP 7.2.0 e removido no PHP 8.0.0. Hoje registam-se autoloaders com spl_autoload_register(), na prática quase sempre através do autoloader gerado pelo Composer.

Preciso de gerar de novo o autoloader depois de criar uma classe nova?

Com regras exclusivamente PSR-4, não; segundo a documentação do Composer, essa é precisamente uma vantagem do PSR-4. Quem usa em produção uma lista de classes otimizada tem de a gerar de novo em cada entrega.

Fontes

Contacto imediato

Cada hora conta. Escreva-nos agora.

Descreva brevemente o sistema, a versão do PHP e o que observou. Entramos em contacto consigo, esclarecemos a situação e trabalhamos remotamente até o incidente estar concluído e documentado.

Ajuda imediata