# Jmenné prostory a autoloading (PSR-4)

> Jmenné prostory a autoloading v PHP podle PSR-4: od názvu třídy k cestě k souboru, spl_autoload_register, autoloader Composeru a kontrola po incidentu

Zdroj: https://phpsos.de/cs/php/namespaces-autoloading/  
Stav: 25.10.2026  
Poskytovatel: PHP SOS, Nouzová pomoc pro PHP a bezpečnost serverů. Okamžitá pomoc přes WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20den%2C%20PHP%20SOS%2C%20pot%C5%99ebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20PHP%20serverem.%20Firma%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**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](https://phpsos.de/cs/php/composer/) 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
<?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
<?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`:

```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](https://phpsos.de/cs/php/psr-standards/).

## 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ů](https://phpsos.de/cs/blog/geaenderte-dateien-finden/) a [Porovnání jádra CMS s originálem](https://phpsos.de/cs/blog/cms-kerndateien-vergleichen/). 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](https://phpsos.de/cs/leistungen/malware-entfernung/) 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

- [PHP-FIG: Autoloader PSR-4](https://www.php-fig.org/psr/psr-4/)
- [Příručka PHP: Jmenné prostory, přehled](https://www.php.net/manual/de/language.namespaces.rationale.php)
- [Příručka PHP: Autoloading](https://www.php.net/manual/de/language.oop5.autoload.php)
- [Composer: Schéma composer.json](https://getcomposer.org/doc/04-schema.md)
