Actuele situatie: PHP2Shell. Twee kritieke PHP-kwetsbaarheden (CVSS 9.2) maken schadelijke code zonder inloggen mogelijk. Patches sinds 21-10-2026.Wat u nu moet doen →

Namespaces en autoloading (PSR-4)

Namespaces ordenen PHP-code, autoloading laadt klassen precies op het moment dat ze nodig zijn. Hier ziet u hoe PSR-4 klassenamen op bestanden afbeeldt en waarom de autoloader na een incident moet worden gecontroleerd.

Stand 5 min. leestijdPHP-kennis

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 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
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
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:

{
    "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.

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 en CMS-kernbestanden met het origineel vergelijken. 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 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

Direct contact

Elk uur telt. Schrijf ons nu.

Beschrijf kort het systeem, de PHP-versie en wat u opmerkt. Wij nemen contact op, brengen de situatie in kaart en werken op afstand tot het incident is afgerond en gedocumenteerd.

Directe hulp