Aktuální situace: PHP2Shell. Dvě kritické zranitelnosti PHP (CVSS 9.2) umožňují spustit škodlivý kód bez přihlášení. Záplaty od 21. 10. 2026.Co nyní udělat →

Jmenné prostory a autoloading (PSR-4)

Jmenné prostory řadí kód PHP, autoloading načítá třídy přesně ve chvíli, kdy jsou potřeba. Zde uvidíte, jak PSR-4 přiřazuje názvy tříd souborům a proč je nutné autoloader po incidentu zkontrolovat.

Stav 4 min čteníZnalosti o PHP

Stručně: Jmenné prostory jsou v PHP něco jako složky pro názvy tříd: App\Rechnung\Pdf a Bibliothek\Pdf mohou existovat vedle sebe, aniž by si překážely. Autoloading zajišťuje, že PHP načte třídu až ve chvíli, kdy je poprvé potřeba. Standard PSR-4 určuje, jak se z názvu třídy stane cesta k souboru; Composer pak vytvoří odpovídající autoloader. Protože tento autoloader běží při každém požadavku, patří po bezpečnostním incidentu k prvním věcem, které se kontrolují.

Proč PHP potřebuje jmenné prostory

Jmenné prostory existují od PHP 5.3.0. Předtím sdílely všechny třídy a funkce jediný globální jmenný prostor. Pokud se dvě knihovny jmenovaly Logger, došlo ke kolizi. Vývojáři si pomáhali dlouhými názvy jako Firma_Modul_Unterbereich_Logger.

Příručka PHP uvádí dva problémy, které jmenné prostory řeší: kolize názvů mezi vlastním kódem, interními třídami PHP a knihovnami třetích stran a příliš dlouhé názvy, které vznikly jen proto, aby se těmto kolizím předešlo. Pro rozhodovatele to znamená: teprve jmenné prostory umožnily prakticky kombinovat v jednom projektu desítky cizích balíčků, jak je dnes s Composerem běžné.

Jmenné prostory v praxi: namespace, use, aliasy

Soubor deklaruje svůj jmenný prostor v prvním příkazu. Pomocí use se přebírají třídy z jiných jmenných prostorů, podle přání pod kratším názvem.

<?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);
    }
}

Úplný název této třídy je App\Rechnung\PdfErzeuger. Úvodní zpětné lomítko u \sprintf výslovně odkazuje na globální funkci PHP.

Autoloading: načítání tříd podle potřeby

Bez autoloadingu by musel každý skript vkládat všechny potřebné soubory pomocí require. Pomocí spl_autoload_register() se místo toho zaregistruje funkce, kterou PHP zavolá, jakmile se použije neznámá třída, rozhraní, trait nebo enum. Funkce dostane název třídy a načte odpovídající soubor.

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

    if (!str_starts_with($klasse, $praefix)) {
        return; // nejsem příslušný, na řadě je další autoloader
    }
    $datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
    if (is_file($datei)) {
        require $datei;
    }
});

spl_autoload_register() lze volat opakovaně. PHP pak registrované autoloadery vyzývá jeden po druhém, dokud některý třídu nenačte. V praxi mají velké aplikace často více autoloaderů: autoloader Composeru pro knihovny, vlastní autoloader CMS a další od pluginů nebo modulů. Pro administrátory z toho plyne: jaký kód se při požadavku skutečně načte, vyplývá ze součinnosti všech těchto autoloaderů, a ne jen ze struktury složek.

Příručka důrazně nedoporučuje v autoloaderu vyhazovat výjimky; PSR-4 to výslovně zakazuje. Starší funkce __autoload() byla v PHP 7.2.0 označena za zastaralou a v PHP 8.0.0 odstraněna.

PSR-4: od názvu třídy k cestě k souboru

PSR-4 je standard PHP-FIG. Úplný název třídy začíná jmenným prostorem výrobce. Prefix jmenného prostoru se přiřadí základnímu adresáři, zbytek názvu dává podsložky a soubor končí na .php. Velká a malá písmena se musí přesně shodovat. Takto vypadá přiřazení v composer.json:

{
    "autoload": {
        "psr-4": { "App\\": "src/" }
    }
}
Název třídy Soubor
App\Kunde\Kunde src/Kunde/Kunde.php
App\Rechnung\PdfErzeuger src/Rechnung/PdfErzeuger.php
App\Rechnung\Pdf\Vorlage src/Rechnung/Pdf/Vorlage.php

Klasickým úskalím je velikost písmen. Na vývojových počítačích s Windows nebo macOS souborový systém často nerozlišuje mezi Kunde.php a kunde.php, na serveru s Linuxem ano. Aplikace, která běží lokálně, pak na serveru třídu nenajde. Pravidlo z PSR-4, používat názvy přesně ve správném pravopisu, takovým překvapením při nasazení předchází.

Vedle psr-4 zná Composer classmap pro kód bez standardní struktury a files pro soubory, které se načítají při každém požadavku, například pomocné funkce. Další standardy PHP-FIG popisuje stránka Standardy PSR.

Optimalizace autoloaderu v produkci

V produkci autoloader nejlépe nehledá v souborovém systému, ale vyhledává v hotovém seznamu. Composer k tomu nabízí dva stupně:

  1. composer install --no-dev --optimize-autoloader převede pravidla PSR-4 na seznam tříd. Podle dokumentace Composeru se to pro produkci doporučuje.
  2. --classmap-authoritative jde dál: třídy se načítají výhradně ze seznamu. Soubory, které v něm nejsou, autoloader vůbec nenačte.
  3. Při každém nasazení se seznam vytvoří znovu, aby se nové třídy našly.

Autoloading a bezpečnost po PHP2Shell

PHP2Shell se týká interpretu PHP, ne autoloaderu. Povinná zůstává aktualizace na PHP 8.5.12, 8.4.27, 8.3.36 nebo 8.2.35 a restart všech workerů. Po možném incidentu si ale autoloader zaslouží zvláštní pozornost: vendor/autoload.php a všechny soubory uvedené v files se spouštějí při každém požadavku. Řádek, který sem útočník propašuje, tedy působí na celém webu, aniž by ve složce s nahranými soubory ležel nápadný nový soubor.

Zkontrolujte proto, zda vendor a soubory autoloadu odpovídají ověřenému stavu ze správy verzí. Užitečné jsou články Hledání nedávno změněných souborů a Porovnání jádra CMS s originálem. V případě pochybností je čerstvě vytvořený vendor ze zámkového souboru bezpečnější než jakákoli jednotlivá oprava.

Jak konkrétně pomáhá PHP SOS?

  • Porovnáme vendor, autoloader a vstupní soubory s ověřeným stavem a označíme každou odchylku.
  • Obnovíme stav balíčků ze zámkového souboru a nastavíme optimalizovaný autoloader.
  • Zkontrolujeme, zda je ve webrootu jen veřejná složka a zdrojový kód není dosažitelný přímo přes URL.
  • Při napadení převezmeme vyčištění v rámci odstranění malwaru a výsledek zdokumentujeme.

Časté dotazy

Od kdy existují jmenné prostory v PHP?

Od PHP 5.3.0. Podle příručky řeší dva problémy: kolize názvů mezi vlastním kódem, PHP a knihovnami třetích stran a příliš dlouhé názvy tříd, které vznikaly jen proto, aby se takovým kolizím předešlo.

Jaký je rozdíl mezi PSR-0 a PSR-4?

Oba přiřazují názvy tříd cestám k souborům. U PSR-4 se prefix jmenného prostoru v cestě k souboru neopakuje, což dává plošší adresářovou strukturu. PSR-0 je u PHP-FIG označeno jako zastaralé, PSR-4 je doporučený standard.

Funguje __autoload() ještě?

Ne. __autoload() bylo v PHP 7.2.0 označeno za zastaralé a v PHP 8.0.0 odstraněno. Dnes se autoloadery registrují pomocí spl_autoload_register(), v praxi většinou přes autoloader vytvořený Composerem.

Musím po vytvoření nové třídy autoloader znovu vygenerovat?

U čistých pravidel PSR-4 ne, podle dokumentace Composeru je to právě výhoda PSR-4. Kdo v produkci používá optimalizovaný seznam tříd, musí ho při každém nasazení vytvořit znovu.

Zdroje

Okamžitý kontakt

Každá hodina se počítá. Napište nám hned.

Stručně popište systém, verzi PHP a pozorování. Ozveme se, vyjasníme situaci a budeme pracovat na dálku, dokud nebude incident uzavřen a zdokumentován.

Okamžitá pomoc