# Przestrzenie nazw i autoloading (PSR-4)

> Przestrzenie nazw PHP i autoloading z PSR-4: od nazwy klasy do ścieżki pliku, spl_autoload_register, autoloader Composera i kontrola po incydentach.

Źródło: https://phpsos.de/pl/php/namespaces-autoloading/  
Stan: 25.10.2026  
Dostawca: PHP SOS, Pomoc awaryjna PHP i bezpieczeństwo serwerów. Natychmiastowa pomoc przez WhatsApp: https://wa.me/491736494914?text=Dzie%C5%84%20dobry%2C%20PHP%20SOS%2C%20potrzebujemy%20pomocy%20z%20naszym%20serwerem%20PHP.%20Firma%3A%20%E2%80%A6%20Strona%20internetowa%3A%20%E2%80%A6

**Krótko:** Przestrzenie nazw są w PHP czymś w rodzaju folderów dla nazw klas: `App\Rechnung\Pdf` i `Bibliothek\Pdf` mogą istnieć obok siebie, nie przeszkadzając sobie. Autoloading sprawia, że PHP ładuje klasę dopiero wtedy, gdy jest po raz pierwszy potrzebna. Standard PSR-4 określa, jak z nazwy klasy powstaje ścieżka pliku; Composer generuje potem odpowiedni autoloader. Ponieważ ten autoloader działa przy każdym żądaniu, po incydencie bezpieczeństwa należy do pierwszych rzeczy, które się sprawdza.

## Dlaczego PHP potrzebuje przestrzeni nazw

Przestrzenie nazw istnieją od PHP 5.3.0. Wcześniej wszystkie klasy i funkcje dzieliły jedną globalną przestrzeń nazw. Jeśli dwie biblioteki nazywały się `Logger`, dochodziło do kolizji. Programiści radzili sobie długimi nazwami, takimi jak `Firma_Modul_Unterbereich_Logger`.

Podręcznik PHP wymienia dwa problemy, które rozwiązują przestrzenie nazw: kolizje nazw między własnym kodem, klasami wewnętrznymi PHP i bibliotekami podmiotów trzecich oraz zbyt długie nazwy, które powstały tylko po to, by te kolizje obejść. Dla osób podejmujących decyzje oznacza to, że dopiero przestrzenie nazw umożliwiły w praktyce łączenie w jednym projekcie dziesiątek obcych pakietów, jak to jest dziś zwyczajem z [Composerem](https://phpsos.de/pl/php/composer/).

## Przestrzenie nazw w praktyce: namespace, use, aliasy

Plik deklaruje swoją przestrzeń nazw w pierwszej instrukcji. Za pomocą `use` sprowadza się klasy z innych przestrzeni nazw, w razie potrzeby pod krótszą nazwą.

```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);
    }
}
```

Pełna nazwa tej klasy brzmi `App\Rechnung\PdfErzeuger`. Wiodący ukośnik odwrotny przy `\sprintf` jednoznacznie wskazuje globalną funkcję PHP.

## Autoloading: ładowanie klas w razie potrzeby

Bez autoloadingu każdy skrypt musiałby dołączać wszystkie potrzebne pliki za pomocą `require`. Zamiast tego za pomocą `spl_autoload_register()` rejestruje się funkcję, którą PHP wywołuje, gdy tylko użyta zostanie nieznana klasa, interfejs, trait lub enum. Otrzymuje ona nazwę klasy i ładuje odpowiedni plik.

```php
<?php
spl_autoload_register(function (string $klasse): void {
    $praefix = 'App\\';
    $basis   = __DIR__ . '/src/';

    if (!str_starts_with($klasse, $praefix)) {
        return; // niewłaściwy autoloader, kolej na następny
    }
    $datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
    if (is_file($datei)) {
        require $datei;
    }
});
```

`spl_autoload_register()` można wywoływać wielokrotnie. PHP odpytuje wtedy zarejestrowane autoloadery po kolei, aż któryś załaduje klasę. W praktyce duże aplikacje mają ich często kilka: autoloader Composera dla bibliotek, własny autoloader CMS i kolejne od wtyczek lub modułów. Dla administratorów oznacza to, że to, jaki kod zostanie faktycznie załadowany przy żądaniu, wynika ze współdziałania wszystkich tych autoloaderów, a nie wyłącznie ze struktury katalogów.

Podręcznik stanowczo odradza zgłaszanie wyjątków w autoloaderze; PSR-4 wyraźnie tego zabrania. Starsza funkcja `__autoload()` została oznaczona jako przestarzała w PHP 7.2.0 i usunięta w PHP 8.0.0.

## PSR-4: od nazwy klasy do ścieżki pliku

PSR-4 to standard PHP-FIG. Pełna nazwa klasy zaczyna się od przestrzeni nazw producenta. Prefiks przestrzeni nazw jest przypisany do katalogu bazowego, reszta nazwy daje podkatalogi, a plik kończy się na `.php`. Wielkość liter musi się dokładnie zgadzać. Tak wygląda przypisanie w `composer.json`:

```json
{
    "autoload": {
        "psr-4": { "App\\": "src/" }
    }
}
```

| Nazwa klasy | Plik |
|---|---|
| `App\Kunde\Kunde` | `src/Kunde/Kunde.php` |
| `App\Rechnung\PdfErzeuger` | `src/Rechnung/PdfErzeuger.php` |
| `App\Rechnung\Pdf\Vorlage` | `src/Rechnung/Pdf/Vorlage.php` |

Klasyczną pułapką jest wielkość liter. Na komputerach deweloperskich z Windows lub macOS system plików często nie rozróżnia `Kunde.php` i `kunde.php`, a na serwerze Linux tak. Aplikacja, która działa lokalnie, nie znajduje wtedy klasy na serwerze. Reguła z PSR-4, aby używać nazw dokładnie w poprawnej pisowni, zapobiega takim niespodziankom przy wdrożeniu.

Obok `psr-4` Composer zna `classmap` dla kodu bez standardowej struktury oraz `files` dla plików ładowanych przy każdym żądaniu, na przykład funkcji pomocniczych. Dalsze standardy PHP-FIG opisuje strona [Standardy PSR](https://phpsos.de/pl/php/psr-standards/).

## Optymalizacja autoloadera w produkcji

W produkcji autoloader najlepiej nie szuka już w systemie plików, lecz zagląda do gotowej listy. Composer oferuje w tym celu dwa stopnie:

1. `composer install --no-dev --optimize-autoloader` zamienia reguły PSR-4 na listę klas. Według dokumentacji Composera jest to zalecane dla produkcji.
2. `--classmap-authoritative` idzie dalej: klasy są ładowane wyłącznie z listy. Nieuwzględnionych plików autoloader wtedy w ogóle nie ładuje.
3. Przy każdym wdrożeniu lista jest generowana od nowa, aby nowe klasy zostały znalezione.

## Autoloading a bezpieczeństwo po PHP2Shell

PHP2Shell dotyczy interpretera PHP, a nie autoloadera. Obowiązkowa pozostaje aktualizacja do PHP 8.5.12, 8.4.27, 8.3.36 lub 8.2.35 i restart wszystkich workerów. Po możliwym incydencie autoloader zasługuje jednak na szczególną uwagę: `vendor/autoload.php` i wszystkie pliki wpisane w `files` są wykonywane przy każdym żądaniu. Wprowadzony tam wiersz działa więc na całej stronie, bez rzucającego się w oczy nowego pliku w katalogu z przesłanymi plikami.

Proszę zatem sprawdzić, czy `vendor` i pliki autoloadera zgadzają się ze sprawdzonym stanem z systemu kontroli wersji. Pomocne są artykuły [Wyszukiwanie ostatnio zmienionych plików](https://phpsos.de/pl/blog/geaenderte-dateien-finden/) oraz [Porównywanie plików rdzenia CMS z oryginałem](https://phpsos.de/pl/blog/cms-kerndateien-vergleichen/). W razie wątpliwości świeżo wygenerowany `vendor` z pliku lock jest bezpieczniejszy niż jakakolwiek pojedyncza naprawa.

## Jak konkretnie pomaga PHP SOS?

- Porównujemy `vendor`, autoloader i pliki wejściowe ze sprawdzonym stanem i oznaczamy każde odstępstwo.
- Odtwarzamy zestaw pakietów z pliku lock i konfigurujemy zoptymalizowany autoloader.
- Sprawdzamy, czy w webrootcie leży tylko katalog publiczny, a kod źródłowy nie jest bezpośrednio dostępny przez URL.
- W razie infekcji przejmujemy oczyszczanie w ramach [usuwania malware](https://phpsos.de/pl/leistungen/malware-entfernung/) i dokumentujemy wynik.


## Częste pytania

**Od kiedy w PHP istnieją przestrzenie nazw?**  
Od PHP 5.3.0. Według podręcznika rozwiązują dwa problemy: kolizje nazw między własnym kodem, PHP i bibliotekami podmiotów trzecich oraz zbyt długie nazwy klas, które powstawały tylko po to, by takim kolizjom zapobiec.

**Jaka jest różnica między PSR-0 a PSR-4?**  
Oba odwzorowują nazwy klas na ścieżki plików. W PSR-4 prefiks przestrzeni nazw nie jest powtarzany w ścieżce pliku, co daje płytsze katalogi. PSR-0 jest w PHP-FIG uznany za przestarzały, a PSR-4 jest zalecanym standardem.

**Czy __autoload() jeszcze działa?**  
Nie. __autoload() oznaczono jako przestarzałe w PHP 7.2.0 i usunięto w PHP 8.0.0. Dziś autoloadery rejestruje się za pomocą spl_autoload_register(), w praktyce zwykle przez autoloader generowany przez Composera.

**Czy po dodaniu nowej klasy muszę ponownie wygenerować autoloader?**  
Przy samych regułach PSR-4 nie, według dokumentacji Composera jest to właśnie zaleta PSR-4. Kto używa w produkcji zoptymalizowanej listy klas, musi ją generować od nowa przy każdym wdrożeniu.

## Źródła

- [PHP-FIG: autoloader PSR-4](https://www.php-fig.org/psr/psr-4/)
- [Podręcznik PHP: przestrzenie nazw, przegląd](https://www.php.net/manual/de/language.namespaces.rationale.php)
- [Podręcznik PHP: autoloading](https://www.php.net/manual/de/language.oop5.autoload.php)
- [Composer: schemat composer.json](https://getcomposer.org/doc/04-schema.md)
