# Namespaces en autoloading (PSR-4)

> PHP-namespaces en autoloading met PSR-4: van klassenaam naar bestandspad, spl_autoload_register, de Composer-autoloader en controle na incidenten.

Bron: https://phpsos.de/nl/php/namespaces-autoloading/  
Stand: 25-10-2026  
Aanbieder: PHP SOS, PHP-noodhulp en serverbeveiliging. Directe hulp via WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wij%20hebben%20hulp%20nodig%20met%20onze%20PHP-server.%20Bedrijf%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kort gezegd:** Namespaces zijn in PHP iets als mappen voor klassenamen: `App\Rechnung\Pdf` en `Bibliothek\Pdf` kunnen naast elkaar bestaan zonder elkaar te storen. Autoloading zorgt ervoor dat PHP een klasse pas laadt wanneer ze voor het eerst nodig is. De standaard PSR-4 legt vast hoe uit een klassenaam een bestandspad ontstaat; Composer genereert vervolgens de bijpassende autoloader. Omdat deze autoloader bij elk verzoek draait, hoort hij na een beveiligingsincident tot de eerste dingen die worden gecontroleerd.

## Waarom PHP namespaces nodig heeft

Namespaces bestaan sinds PHP 5.3.0. Daarvoor deelden alle klassen en functies één enkele globale naamruimte. Heetten twee bibliotheken `Logger`, dan ging het mis. Ontwikkelaars hielpen zich met lange namen zoals `Firma_Modul_Unterbereich_Logger`.

De PHP-handleiding noemt twee problemen die namespaces oplossen: naamconflicten tussen eigen code, interne PHP-klassen en bibliotheken van derden, en overlange namen die alleen zijn ontstaan om deze conflicten te omzeilen. Voor beslissers betekent dat: pas namespaces hebben het praktisch haalbaar gemaakt om tientallen externe pakketten in één project te combineren, zoals dat met [Composer](https://phpsos.de/nl/php/composer/) tegenwoordig gebruikelijk is.

## Namespaces in de praktijk: namespace, use, aliassen

Een bestand declareert zijn namespace in de eerste instructie. Met `use` haalt men klassen uit andere namespaces binnen, desgewenst onder een kortere naam.

```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);
    }
}
```

De volledige naam van deze klasse luidt `App\Rechnung\PdfErzeuger`. De voorloop-backslash bij `\sprintf` verwijst uitdrukkelijk naar de globale PHP-functie.

## Autoloading: klassen laden wanneer nodig

Zonder autoloading zou elk script alle benodigde bestanden met `require` moeten insluiten. Met `spl_autoload_register()` registreert men in plaats daarvan een functie die PHP aanroept zodra een onbekende klasse, interface, trait of enum wordt gebruikt. Ze krijgt de klassenaam en laadt het bijpassende bestand.

```php
<?php
spl_autoload_register(function (string $klasse): void {
    $praefix = 'App\\';
    $basis   = __DIR__ . '/src/';

    if (!str_starts_with($klasse, $praefix)) {
        return; // niet verantwoordelijk, de volgende autoloader is aan de beurt
    }
    $datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
    if (is_file($datei)) {
        require $datei;
    }
});
```

`spl_autoload_register()` kan meerdere keren worden aangeroepen. PHP vraagt de geregistreerde autoloaders dan een voor een, tot er een de klasse heeft geladen. In de praktijk hebben grote toepassingen er vaak meerdere: de Composer-autoloader voor bibliotheken, een eigen autoloader van het CMS en nog andere van plugins of modules. Voor beheerders betekent dat: welke code bij een verzoek daadwerkelijk wordt geladen, volgt uit het samenspel van al deze autoloaders en niet alleen uit de mappenstructuur.

De handleiding raadt sterk af om in een autoloader exceptions te werpen; PSR-4 verbiedt het uitdrukkelijk. De oudere functie `__autoload()` werd met PHP 7.2.0 als verouderd gemarkeerd en met PHP 8.0.0 verwijderd.

## PSR-4: van klassenaam naar bestandspad

PSR-4 is een standaard van de PHP-FIG. Een volledige klassenaam begint met een leveranciers-namespace. Een voorvoegsel van de namespace wordt aan een basismap gekoppeld, de rest van de naam levert submappen op, en het bestand eindigt op `.php`. Hoofdletters en kleine letters moeten exact overeenkomen. Zo ziet de koppeling in de `composer.json` eruit:

```json
{
    "autoload": {
        "psr-4": { "App\\": "src/" }
    }
}
```

| Klassenaam | Bestand |
|---|---|
| `App\Kunde\Kunde` | `src/Kunde/Kunde.php` |
| `App\Rechnung\PdfErzeuger` | `src/Rechnung/PdfErzeuger.php` |
| `App\Rechnung\Pdf\Vorlage` | `src/Rechnung/Pdf/Vorlage.php` |

Een klassieke valkuil is het onderscheid tussen hoofdletters en kleine letters. Op ontwikkelcomputers met Windows of macOS maakt het bestandssysteem vaak geen onderscheid tussen `Kunde.php` en `kunde.php`, op een Linux-server wel. Een toepassing die lokaal werkt, vindt dan op de server een klasse niet. De regel uit PSR-4 om namen exact in de juiste schrijfwijze te gebruiken, voorkomt zulke verrassingen bij de oplevering.

Naast `psr-4` kent Composer `classmap` voor code zonder standaardstructuur en `files` voor bestanden die bij elk verzoek worden geladen, zoals hulpfuncties. Verdere standaarden van de PHP-FIG beschrijft de pagina [PSR-standaarden](https://phpsos.de/nl/php/psr-standards/).

## De autoloader in productie optimaliseren

In productie zoekt de autoloader bij voorkeur niet meer in het bestandssysteem, maar kijkt hij in een kant-en-klare lijst. Composer biedt daarvoor twee niveaus:

1. `composer install --no-dev --optimize-autoloader` zet de PSR-4-regels om in een klassenlijst. Dat wordt volgens de Composer-documentatie voor productie aanbevolen.
2. `--classmap-authoritative` gaat verder: klassen worden uitsluitend uit de lijst geladen. Bestanden die niet in de lijst staan, laadt de autoloader dan helemaal niet.
3. Bij elke oplevering wordt de lijst opnieuw gegenereerd, zodat nieuwe klassen worden gevonden.

## Autoloading en beveiliging na PHP2Shell

PHP2Shell betreft de PHP-interpreter, niet de autoloader. Verplicht blijven de update naar PHP 8.5.12, 8.4.27, 8.3.36 of 8.2.35 en de herstart van alle workers. Na een mogelijk incident verdient de autoloader echter bijzondere aandacht: `vendor/autoload.php` en alle onder `files` opgenomen bestanden worden bij elk verzoek uitgevoerd. Een daar binnengesmokkelde regel werkt dus op de hele website, zonder dat er een opvallend nieuw bestand in de uploadmap staat.

Controleer daarom of `vendor` en de autoload-bestanden overeenkomen met de gecontroleerde stand uit de versiebeheer. Nuttig zijn de artikelen [Onlangs gewijzigde bestanden vinden](https://phpsos.de/nl/blog/geaenderte-dateien-finden/) en [CMS-kernbestanden met het origineel vergelijken](https://phpsos.de/nl/blog/cms-kerndateien-vergleichen/). In geval van twijfel is een vers gegenereerde `vendor` uit het lock-bestand veiliger dan elke afzonderlijke reparatie.

## Hoe helpt PHP SOS concreet?

- Wij vergelijken `vendor`, autoloader en ingangsbestanden met de gecontroleerde stand en markeren elke afwijking.
- Wij herstellen de pakketvoorraad vanuit het lock-bestand en richten een geoptimaliseerde autoloader in.
- Wij controleren of alleen de openbare map in de webroot staat en broncode niet rechtstreeks via een URL bereikbaar is.
- Bij besmetting nemen wij de opschoning over in het kader van de [malwareverwijdering](https://phpsos.de/nl/leistungen/malware-entfernung/) en documenteren het resultaat.


## Veelgestelde vragen

**Sinds wanneer zijn er namespaces in PHP?**  
Sinds PHP 5.3.0. Ze lossen volgens de handleiding twee problemen op: naamconflicten tussen eigen code, PHP en bibliotheken van derden, en overlange klassenamen die alleen ontstonden om zulke conflicten te vermijden.

**Wat is het verschil tussen PSR-0 en PSR-4?**  
Beide beelden klassenamen af op bestandspaden. Bij PSR-4 wordt het namespace-voorvoegsel niet in het bestandspad herhaald, wat vlakkere mappenstructuren oplevert. PSR-0 is door de PHP-FIG als verouderd ingedeeld, PSR-4 is de aanbevolen standaard.

**Werkt __autoload() nog?**  
Nee. __autoload() werd met PHP 7.2.0 als verouderd gemarkeerd en met PHP 8.0.0 verwijderd. Tegenwoordig registreert men autoloaders met spl_autoload_register(), in de praktijk meestal via de door Composer gegenereerde autoloader.

**Moet ik na het aanmaken van een nieuwe klasse de autoloader opnieuw genereren?**  
Bij pure PSR-4-regels niet; volgens de Composer-documentatie is dat juist een voordeel van PSR-4. Wie in productie een geoptimaliseerde klassenlijst gebruikt, moet die bij elke oplevering opnieuw genereren.

## Bronnen

- [PHP-FIG: PSR-4 Autoloader](https://www.php-fig.org/psr/psr-4/)
- [PHP-handleiding: namespaces, overzicht](https://www.php.net/manual/de/language.namespaces.rationale.php)
- [PHP-handleiding: autoloading](https://www.php.net/manual/de/language.oop5.autoload.php)
- [Composer: The composer.json schema](https://getcomposer.org/doc/04-schema.md)
