Composer-Autoloading intern: wie PSR-4 wirklich aufgelöst wird
AI generated
<?php
8.4
PHP 8.4 · Composer · PSR-4 · Autoloading
Composer-Autoloading intern
wie PSR-4 wirklich aufgelöst wird

Hinter jedem require-freien PHP-Projekt steckt ein einfacher, aber oft missverstandener Mechanismus: Composer-Autoloading übersetzt Namespace-Deklarationen aus composer.json über generierte PHP-Dateien und eine Longest-Prefix-Match-Logik in tatsächliche Dateipfade. Dieser Artikel öffnet die Blackbox: von composer dump-autoload über autoload_psr4.php bis zur Methode ClassLoader::loadClass(), Schritt für Schritt und mit echtem, nachvollziehbarem Code für PHP 8.4.

18 Min. Lesezeit PSR-4 · ClassLoader · composer dump-autoload PHP 8.4 · Composer 2.x · Framework-unabhängig

1. Warum Autoloading überhaupt, und wieso sich PSR-4 durchgesetzt hat

Vor der Einführung von Autoloading-Mechanismen begann fast jede nicht-triviale PHP-Datei mit einem Wald aus require_once-Anweisungen. Jede Klasse musste manuell eingebunden werden, bevor sie benutzt werden konnte, und mit wachsender Codebasis wuchs auch die Liste der Includes linear mit. Ein vergessenes require_once führte zu einem Fatal Error zur Laufzeit, oft erst dann, wenn der betroffene Codepfad tatsächlich ausgeführt wurde. Mit PHP 5.1.2 kam spl_autoload_register() und damit die Möglichkeit, eine Callback-Funktion zu registrieren, die PHP automatisch aufruft, sobald eine noch unbekannte Klasse referenziert wird. Damit war die technische Grundlage für modernes Composer-Autoloading gelegt, lange bevor Composer selbst existierte.

Die PHP-FIG definierte mit PSR-0 den ersten Standard für Autoloading-Konventionen: Der vollständige, qualifizierte Klassenname inklusive Namespace musste eins zu eins auf einen Verzeichnispfad abgebildet werden, wobei Unterstriche innerhalb eines Klassennamens ebenfalls als Verzeichnistrenner interpretiert wurden. Das funktionierte, erzwang aber tief verschachtelte Ordnerstrukturen und eine Vermischung zweier Trennzeichen-Konventionen. PSR-4 löste dieses Problem, indem es Unterstriche als reguläre Zeichen behandelt und stattdessen ein explizites Mapping von Namespace-Präfix zu Basisverzeichnis erlaubt. Genau dieses Mapping ist heute der Kern jedes PSR-4-Autoloading-Setups in composer.json.

Composer griff PSR-4 nicht nur auf, sondern machte es zum De-facto-Standard des gesamten PHP-Ökosystems. Praktisch jedes moderne Paket auf Packagist deklariert seine Klassen über autoload.psr-4, und Composer-Autoloading hat require_once-Ketten in Anwendungscode nahezu vollständig verdrängt. Wer heute versteht, was hinter diesem scheinbar simplen composer.json-Eintrag tatsächlich passiert, versteht auch, warum PHP-Projekte mit hunderttausenden Klassen in Sekundenbruchteilen die richtige Datei finden.

2. Was composer dump-autoload wirklich generiert

Der Befehl composer dump-autoload wirkt nach außen wie eine Blackbox, erzeugt aber lediglich eine überschaubare Menge reiner PHP-Dateien im Verzeichnis vendor/composer/. Die Datei vendor/autoload.php im Projekt-Root ist der einzige Einstiegspunkt, den ein Entwickler jemals einbinden muss. Sie delegiert sofort an vendor/composer/autoload_real.php, welche die eigentliche Initialisierung übernimmt: einen ClassLoader instanziieren, alle Mapping-Dateien laden und den Loader schließlich bei spl_autoload_register() anmelden. Dieser gesamte Ablauf ist reines generiertes PHP, kein Bytecode, keine Magie, jede Zeile lässt sich mit einem Editor öffnen und nachvollziehen.

Die Datei autoload_psr4.php enthält ein einfaches assoziatives Array, das jedes Namespace-Präfix auf ein oder mehrere Basisverzeichnisse abbildet, exakt aus den autoload.psr-4-Einträgen aller beteiligten composer.json-Dateien zusammengestellt. Ergänzend listet autoload_classmap.php Klassen, die per expliziter Classmap oder Classmap-Scan gefunden wurden, und autoload_files.php enthält Pfade zu Dateien, die bei jedem Request unbedingt eingebunden werden, etwa für globale Hilfsfunktionen. In Projekten mit dem Flag --optimize-autoloader wird zusätzlich autoload_static.php erzeugt, das dieselben Daten als statische Klasseneigenschaften im ComposerStaticInit-Namespace einbettet und dadurch das wiederholte Zusammenbauen der Arrays bei jedem Request überspringt.

Die eigentliche Logik steckt in vendor/composer/ClassLoader.php, einer einzigen, gut lesbaren PHP-Klasse von wenigen hundert Zeilen, die Composer selbst mit jeder Version mitliefert. Sie enthält die komplette Auflösungslogik für PSR-4-Autoloading, PSR-0-Fallback und Classmap-Lookups. Wer verstehen will, wie Composer-Autoloading tatsächlich funktioniert, muss nicht raten oder Dokumentation durchforsten, sondern kann einfach diese eine Datei öffnen, denn sie ist bewusst ohne Framework-Abhängigkeiten und ohne Reflection geschrieben.


<?php

// autoload_psr4.php @generated by Composer
// Maps namespace prefixes to one or more base directories

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'Vendor\\Shop\\' => array($baseDir . '/src/Shop'),
    'Vendor\\Shop\\Tests\\' => array($baseDir . '/tests/Shop'),
    'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
    'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
    'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
);

3. Der PSR-4-Auflösungsalgorithmus Schritt für Schritt

Der PSR-4-Standard beschreibt formal einen einzigen Algorithmus: aus einem vollständig qualifizierten Klassennamen wird ein Dateisystempfad. Der erste Schritt trennt den Namespace vom Klassennamen selbst, wobei der letzte Backslash als Trenner dient. Anschließend sucht der Loader nach dem längsten registrierten Namespace-Präfix, der mit dem Anfang des vollständigen Namespace übereinstimmt. Das ist der entscheidende Punkt: Composer-Autoloading arbeitet nicht mit dem ersten Treffer, sondern immer mit dem spezifischsten, also längsten passenden Präfix, weil mehrere Präfixe gleichzeitig zutreffen können.

Ein Beispiel macht das greifbar: Ist sowohl Vendor\Shop\ als auch Vendor\Shop\Tests\ registriert, und wird die Klasse Vendor\Shop\Tests\Unit\OrderTest gesucht, gewinnt das längere Präfix Vendor\Shop\Tests\, nicht das kürzere Vendor\Shop\. Der Loader entfernt das gefundene Präfix vom Namespace, ersetzt die verbleibenden Backslashes durch Verzeichnistrenner, hängt .php an und kombiniert das Ergebnis mit dem für dieses Präfix hinterlegten Basisverzeichnis. Erst wenn diese zusammengesetzte Datei tatsächlich existiert, wird sie eingebunden, sonst probiert der Algorithmus das nächstkürzere passende Präfix.

Dieser Fallback auf kürzere Präfixe ist wichtig, weil ein Namespace theoretisch auf mehrere Basisverzeichnisse gleichzeitig gemappt sein kann. PSR-4-Autoloading erlaubt explizit, dass ein einzelnes Präfix auf ein Array von Verzeichnissen zeigt, die der Loader der Reihe nach durchprobiert, bis eine Datei gefunden wird. Das ist selten nötig, aber genau dieser Mechanismus erlaubt es zum Beispiel, dieselbe Namespace-Basis in einem Monorepo aus mehreren physisch getrennten Paketen zusammenzusetzen, ohne die Namespace-Struktur künstlich zu verschachteln.


<?php

declare(strict_types=1);

/**
 * Simplified illustration of the PSR-4 longest-prefix-match algorithm
 * as implemented inside Composer's ClassLoader::findFileWithExtension().
 */
final class Psr4Resolver
{
    /** @param array<string, list<string>> $prefixDirsPsr4 */
    public function __construct(
        private readonly array $prefixDirsPsr4,
    ) {
    }

    public function resolve(string $class): ?string
    {
        $subPath = $class;

        // Walk the namespace from the most specific to the least specific segment
        while (($lastPos = strrpos($subPath, '\\')) !== false) {
            $subPath = substr($subPath, 0, $lastPos);
            $search = $subPath . '\\';

            if (!isset($this->prefixDirsPsr4[$search])) {
                continue;
            }

            $relative = substr($class, $lastPos + 1);

            foreach ($this->prefixDirsPsr4[$search] as $dir) {
                $file = $dir . '/' . strtr($relative, '\\', '/') . '.php';
                if (is_file($file)) {
                    return $file;
                }
            }
        }

        return null;
    }
}

4. Die vier Autoload-Typen im composer.json im Vergleich

Composer unterstützt im autoload-Block der composer.json vier grundlegend unterschiedliche Mechanismen, die parallel eingesetzt werden können. psr-4 ist der Standardfall für praktisch jeden modernen Namespace und bildet, wie beschrieben, ein Namespace-Präfix auf ein Basisverzeichnis ab. psr-0 existiert nur noch aus Kompatibilitätsgründen für ältere Pakete, die Unterstriche in Klassennamen als Verzeichnistrenner erwarten, und sollte in neuem Code nicht mehr verwendet werden. Beide Mechanismen basieren auf demselben Prinzip: Ableitung des Pfads aus dem Klassennamen zur Laufzeit, ohne dass jede einzelne Klasse vorher bekannt sein muss.

classmap funktioniert grundlegend anders: Composer durchsucht beim dump-autoload-Lauf die angegebenen Verzeichnisse und Dateien rekursiv nach Klassendefinitionen und trägt jede gefundene Klasse mit ihrem exakten Dateipfad in eine statische Lookup-Tabelle ein. Das eliminiert jede Laufzeit-Konvention, kostet aber Zeit beim Dump und erfordert einen erneuten Lauf, sobald neue Klassen hinzukommen oder umbenannt werden. Ältere Bibliotheken ohne PSR-4-Struktur, etwa mit inkonsistenter Namespace-zu-Verzeichnis-Zuordnung, nutzen häufig classmap, weil Composer-Autoloading hier keine strukturellen Vorgaben macht.

files schließlich ist kein Klassenmapping im eigentlichen Sinn, sondern eine simple Liste von Dateipfaden, die bei jedem einzelnen Request bedingungslos eingebunden werden, etwa für globale Funktionsbibliotheken oder Konstanten, die außerhalb jeder Klasse definiert sind. Weil files-Einträge bei jedem Request geladen werden, sollte diese Liste bewusst klein gehalten werden. Alle vier Typen greifen im selben generierten ClassLoader ineinander, und PSR-4-Autoloading deckt in der Praxis über neunzig Prozent aller Fälle ab.


{
    "autoload": {
        "psr-4": {
            "Vendor\\Shop\\": "src/Shop/"
        },
        "psr-0": {
            "Legacy_": "legacy/"
        },
        "classmap": [
            "src/Legacy/",
            "src/Compat/OldParser.php"
        ],
        "files": [
            "src/functions.php",
            "src/constants.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Vendor\\Shop\\Tests\\": "tests/"
        }
    }
}

5. ClassLoader::loadClass() intern nachgebaut

Die Methode ClassLoader::loadClass() ist die einzige Funktion, die tatsächlich bei spl_autoload_register() registriert wird, und damit der einzige Codepfad, der bei jeder unbekannten Klasse ausgeführt wird. Intern delegiert sie an findFile(), die zunächst in der Classmap nachschlägt, weil ein direkter Array-Lookup schneller ist als jede Präfix-Berechnung. Erst wenn dort kein Treffer existiert, prüft sie die PSR-4- und danach die PSR-0-Mappings, jeweils mit der im vorherigen Abschnitt beschriebenen Longest-Prefix-Logik. Genau diese Reihenfolge, Classmap vor PSR-4-Autoloading, ist der Grund, warum --optimize-autoloader so wirksam ist.

Ein Detail, das oft übersehen wird: findFile() cached negative Treffer nicht standardmäßig, es sei denn, APCu-Unterstützung ist aktiv. Ohne diesen Cache wird für jede Klasse, die nicht gefunden werden kann, bei jedem Request erneut der komplette Präfix-Baum durchlaufen, inklusive aller Dateisystem-Zugriffe mit is_file(). Das nachgebaute Beispiel im vorherigen Abschnitt zeigt bereits die Kernidee, aber der echte ClassLoader ergänzt zusätzlich Fallback-Verzeichnisse, PSR-0-Unterstützung für Unterstrich-Namespaces und die optionale APCu-Cache-Schicht, ohne die grundsätzliche Reihenfolge zu ändern.

Wichtig für das Verständnis von Composer-Autoloading ist, dass loadClass() keinen Fehler wirft, wenn keine Datei gefunden wird. Sie gibt schlicht null zurück, und PHP registriert daraufhin die nächste Autoload-Funktion in der Kette, falls mehrere registriert sind, bevor letztlich ein Class not found-Fatal-Error entsteht. Diese stille Rückgabe ist bewusst so gestaltet, damit mehrere Autoloader nebeneinander koexistieren können, etwa wenn ein Framework zusätzlich einen eigenen Loader registriert.


<?php

declare(strict_types=1);

/**
 * Simplified reconstruction of Composer\Autoload\ClassLoader::loadClass()
 * showing the real lookup order: classmap first, then PSR-4, then PSR-0.
 */
final class RebuiltClassLoader
{
    /**
     * @param array<class-string, string>   $classMap
     * @param array<string, list<string>>   $prefixDirsPsr4
     */
    public function __construct(
        private readonly array $classMap,
        private readonly array $prefixDirsPsr4,
    ) {
    }

    public function loadClass(string $class): bool
    {
        $file = $this->findFile($class);

        if ($file !== null) {
            require $file;
            return true;
        }

        return false;
    }

    private function findFile(string $class): ?string
    {
        // 1. Classmap lookup, a plain array access, fastest possible path
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }

        // 2. PSR-4 longest-prefix match (see Psr4Resolver above)
        $resolver = new Psr4Resolver($this->prefixDirsPsr4);
        $file = $resolver->resolve($class);

        // No file found: return null, let the next registered autoloader try
        return $file;
    }
}

6. Performance-Tuning: optimize-autoloader, classmap-authoritative, apcu-autoloader

Ohne Optimierung führt Composer-Autoloading bei jeder unbekannten Klasse die vollständige Präfix-Suche samt Dateisystem-Zugriffen erneut aus. Das Flag --optimize-autoloader löst dieses Problem, indem es beim dump-autoload-Lauf für jede PSR-4- und PSR-0-Klasse, die es im Projekt findet, den exakten Dateipfad in eine statische Classmap einträgt. Die generierte autoload_static.php enthält dann bereits alle bekannten Klassen als direkte Array-Einträge, wodurch die Longest-Prefix-Logik für diese Klassen komplett entfällt. In Produktionsumgebungen ist dieses Flag praktisch immer aktiv, in lokalen Entwicklungsumgebungen dagegen bewusst deaktiviert, weil neu erstellte Klassen sonst erst nach einem erneuten Dump gefunden würden.

--classmap-authoritative geht einen Schritt weiter und deklariert die generierte Classmap als vollständig und verbindlich. Wird eine Klasse dort nicht gefunden, versucht der Loader gar nicht erst, sie über PSR-4-Regeln aufzulösen, sondern gibt sofort false zurück. Das spart weitere Dateisystem-Zugriffe, bedeutet aber auch, dass jede neue oder umbenannte Klasse zwingend einen erneuten composer dump-autoload -o-Lauf voraussetzt, sonst schlägt das Laden ohne erkennbaren Grund fehl. Diese Option eignet sich ausschließlich für unveränderliche Deployment-Artefakte, niemals für aktive Entwicklungsumgebungen.

--apcu-autoloader verfolgt einen orthogonalen Ansatz: Statt die Classmap statisch vorzuberechnen, wird jedes Lookup-Ergebnis, positiv wie negativ, im APCu-Shared-Memory-Cache abgelegt. Das ist besonders wertvoll bei sehr großen Codebasen mit vielen Klassen, die nur selten geladen werden, weil PSR-4-Autoloading hier nicht bei jedem Request neu rechnen muss, sondern direkt aus dem prozessübergreifenden Cache liest. In der Praxis kombiniert man --optimize-autoloader und --apcu-autoloader häufig, weil sie unterschiedliche Schwachstellen adressieren: die eine reduziert CPU-Arbeit pro Request, die andere überbrückt Klassen, die aus irgendeinem Grund nicht im Optimierungslauf erfasst wurden.

7. Eigene Autoloading-Strategien

In größeren Projekten reicht ein einzelnes Namespace-zu-Verzeichnis-Mapping selten aus. Ein verbreitetes Muster ist, mehrere verwandte Namespaces auf dasselbe physische Verzeichnis abzubilden, etwa wenn ein Modul intern in mehrere logische Namespaces gegliedert ist, aber als ein einziges Composer-Paket ausgeliefert wird. Composer-Autoloading erlaubt das problemlos, solange jedes Präfix eindeutig registriert ist und die Longest-Prefix-Regel bei Überschneidungen greift. Wichtig ist dabei, die Präfixe bewusst zu wählen, damit keine ungewollte Mehrdeutigkeit entsteht, die erst zur Laufzeit auffällt.

Test-Namespaces sollten strikt vom Produktivcode getrennt werden, sowohl im Dateisystem als auch im Autoload-Mapping. Der übliche Ansatz nutzt autoload-dev statt autoload für Test-Namespaces, wodurch diese Mappings ausschließlich bei composer install ohne --no-dev aktiv sind und in Produktions-Deployments komplett fehlen. Das verhindert, dass Test-Doubles, Fixtures oder Mock-Klassen versehentlich in einem Produktions-Build landen, nur weil sie technisch über einen gültigen PSR-4-Autoloading-Pfad erreichbar wären.

Wer zusätzliche Kontrolle über die Ladereihenfolge braucht, kann nach der Standardinitialisierung eigene Autoloader mit spl_autoload_register() registrieren, etwa für generierten Code, Proxy-Klassen oder Plugin-Systeme mit dynamischen Klassennamen zur Laufzeit. Solche Loader sollten defensiv geschrieben sein und bei Nichtfund konsequent false zurückgeben, damit sie sich nahtlos in die bestehende Kette aus Composer-Autoloading und eigenen Fallback-Mechanismen einfügen, statt sie zu blockieren.


<?php

declare(strict_types=1);

// Register a project-specific autoloader after Composer's own loader,
// e.g. for dynamically generated proxy classes in a cache directory.
spl_autoload_register(function (string $class): bool {
    if (!str_starts_with($class, 'App\\Proxy\\')) {
        return false; // not our namespace, let the next loader try
    }

    $shortName = substr($class, strlen('App\\Proxy\\'));
    $file = __DIR__ . '/var/cache/proxies/' . $shortName . '.php';

    if (!is_file($file)) {
        return false;
    }

    require $file;
    return true;
}, true, false);

8. Häufige Fehler und Debugging

Der mit Abstand häufigste Fehler bei Composer-Autoloading betrifft Case-Sensitivity. Auf Linux-Dateisystemen sind Dateinamen case-sensitive, auf macOS und Windows in der Standardkonfiguration case-insensitive. Ein Entwickler, der lokal auf macOS eine Klasse OrderService in einer Datei orderservice.php ablegt, sieht dort keinen Fehler, weil das Dateisystem Groß- und Kleinschreibung ignoriert. Derselbe Code schlägt auf einem Linux-Produktionsserver oder in einer CI-Pipeline mit einem Class not found-Fehler fehl, weil OrderService.php und orderservice.php dort zwei unterschiedliche Dateien sind.

Ein zweiter typischer Fehler ist eine falsche Verzeichnisstruktur relativ zum in composer.json deklarierten Basisverzeichnis. Wird der Namespace Vendor\Shop\ auf src/Shop/ gemappt, muss die Klasse Vendor\Shop\Service\OrderService exakt unter src/Shop/Service/OrderService.php liegen, kein Verzeichnis mehr, keins weniger. Ein zusätzliches Zwischenverzeichnis oder ein fehlendes Unterverzeichnis führt zu genau demselben Class not found-Fehler, unabhängig davon, ob PSR-4-Autoloading oder Classmap verwendet wird, weil der Loader den Pfad strikt aus dem Namespace ableitet.

Der dritte Klassiker: vergessenes composer dump-autoload nach dem Umbenennen oder Verschieben von Klassen, insbesondere in Projekten mit aktivierter Classmap oder aktiviertem --optimize-autoloader. Die alte, jetzt veraltete Zuordnung bleibt in den generierten Dateien stehen, bis ein neuer Dump-Lauf sie aktualisiert. Das äußert sich oft als scheinbar zufälliger Fehler, der nur bei bestimmten Klassen auftritt und Entwickler in die falsche Richtung führt, weil der Code selbst korrekt ist und ausschließlich die generierten Autoload-Dateien veraltet sind. Ein einfaches composer dump-autoload nach jeder strukturellen Änderung verhindert dieses Problem zuverlässig.

9. Alle Autoload-Typen im direkten Vergleich

Die vier vorgestellten Mechanismen unterscheiden sich deutlich in Performance-Charakteristik, Wartungsaufwand und Einsatzgebiet. Die folgende Übersicht fasst zusammen, wann welcher Ansatz innerhalb von Composer-Autoloading sinnvoll ist und welche Kompromisse er jeweils mit sich bringt.

Typ Use-Case Performance Wann verwenden
psr-4 Standard-Autoloading für eigenen und modernen Third-Party-Code Sehr gut mit --optimize-autoloader Für jeden neuen Namespace, praktisch immer
psr-0 Legacy-Pakete mit Unterstrich-Namespaces Etwas langsamer, tiefere Verzeichnisse Nur für Altlasten-Kompatibilität
classmap Inkonsistente oder nicht-PSR-4-konforme Verzeichnisstrukturen Sehr schnell nach Dump, direkter Array-Lookup Für Altcode ohne saubere Namespace-Struktur
files Globale Funktionen, Konstanten außerhalb von Klassen Geringer Overhead, aber bei jedem Request geladen Nur für wenige, kleine globale Dateien

In der Praxis kombinieren die meisten Projekte psr-4 als Standard für den gesamten eigenen Code mit vereinzelten classmap-Einträgen für Altlasten und wenigen files-Einträgen für globale Hilfsfunktionen. psr-0 taucht heute fast ausschließlich noch als Abhängigkeit älterer Third-Party-Pakete auf. Die Wahl des richtigen Typs für PSR-4-Autoloading-basierte Projekte ist damit selten eine echte Entscheidung, sondern folgt der Struktur der jeweiligen Abhängigkeit.

10. Zusammenfassung

Composer-Autoloading ist im Kern ein überschaubarer, vollständig nachvollziehbarer Mechanismus: composer.json deklariert Namespace-Mappings, composer dump-autoload übersetzt diese Deklarationen in generierte PHP-Dateien, und ClassLoader::loadClass() wendet zur Laufzeit die Longest-Prefix-Match-Logik von PSR-4 an, mit Classmap-Lookup als schnellstem Vorab-Check. Wer diese Kette einmal Datei für Datei nachvollzogen hat, verliert die Scheu vor Autoloading-Problemen, weil jeder Fehler auf eine der wenigen bekannten Ursachen zurückzuführen ist: falsche Verzeichnisstruktur, Case-Sensitivity-Unterschiede zwischen Betriebssystemen oder ein vergessener Dump-Lauf nach struktureller Änderung.

Für den produktiven Einsatz zahlen sich --optimize-autoloader und in großen Codebasen zusätzlich --apcu-autoloader messbar aus, weil sie genau die Präfix-Suche überspringen, die bei jeder unbekannten Klasse sonst erneut durchlaufen würde. --classmap-authoritative bringt weitere Geschwindigkeit, verlangt im Gegenzug Disziplin bei jedem Deployment. Wer PSR-4-Autoloading korrekt strukturiert, saubere Test-Namespace-Trennung über autoload-dev pflegt und Performance-Flags gezielt für Produktionsumgebungen aktiviert, bekommt ein Autoloading-System, das in Sekundenbruchteilen zuverlässig jede Klasse findet, unabhängig von der Größe der Codebasis.

Composer-Autoloading und PSR-4: Das Wichtigste auf einen Blick

Generierte Dateien

autoload_psr4.php, autoload_static.php, autoload_real.php und ClassLoader.php in vendor/composer/, reines, nachvollziehbares PHP.

Auflösungslogik

Classmap-Lookup zuerst, dann PSR-4-Longest-Prefix-Match, dann PSR-0-Fallback. Kein Treffer: null, nächster Autoloader übernimmt.

Performance-Flags

--optimize-autoloader, --classmap-authoritative und --apcu-autoloader für Produktionsumgebungen.

Häufigste Fehlerquelle

Case-Sensitivity zwischen Linux und macOS, falsche Verzeichnisstruktur, vergessenes composer dump-autoload.

11. FAQ: Composer-Autoloading und PSR-4

1Was ist Composer-Autoloading genau?
Der Mechanismus, mit dem Composer aus autoload-Deklarationen generierte PHP-Dateien erzeugt, die über spl_autoload_register() automatisch die passende Datei für jede Klasse laden.
2Warum ist PSR-4 besser als PSR-0?
PSR-4 nutzt ein explizites Präfix-zu-Verzeichnis-Mapping statt Unterstriche als Verzeichnistrenner zu erzwingen, das ergibt flachere, klarere Strukturen.
3Was erzeugt composer dump-autoload?
Reine PHP-Dateien in vendor/composer/: autoload_psr4.php, autoload_classmap.php, autoload_files.php, autoload_real.php und ClassLoader.php.
4Wie funktioniert Longest-Prefix-Match?
Der Loader wählt unter allen passenden Präfixen immer das längste, spezifischste, und übersetzt erst dann den Rest in einen Dateipfad.
5Was bewirkt --optimize-autoloader?
Trägt jeden gefundenen Klassenpfad in eine statische Classmap ein, die Präfix-Suche zur Laufzeit entfällt dadurch komplett.
6Wann --classmap-authoritative verwenden?
Nur in unveränderlichen Deployments. Kein PSR-4-Fallback bei Miss, jede neue Klasse erfordert zwingend einen erneuten Dump-Lauf.
7Was macht --apcu-autoloader?
Speichert jedes Lookup-Ergebnis im APCu-Cache, nachfolgende Requests lesen direkt daraus, statt neu zu suchen.
8Läuft lokal, aber nicht auf dem Server?
Meist Case-Sensitivity: macOS ignoriert Groß-/Kleinschreibung bei Dateinamen, Linux nicht. Führt zu Class not found nur in Produktion.
9Wann classmap statt psr-4 nutzen?
Bei Bibliotheken ohne konsistente Namespace-zu-Verzeichnis-Zuordnung. classmap scannt einmalig und trägt exakte Pfade ein, unabhängig von der Struktur.
10Immer dump-autoload nach neuer Klasse?
Bei reinem PSR-4 ohne Optimierungsflags nicht nötig. Mit Classmap, optimize-autoloader oder classmap-authoritative ist ein erneuter Dump zwingend.

Mironsoft

PHP-Architektur, Composer-Tooling und Performance-Audits

Autoloading-Probleme, die niemand im Team erklären kann?

Wir analysieren bestehende PHP-Projekte, decken fehlerhafte Composer-Autoloading-Konfigurationen auf und optimieren ClassLoader-Performance mit optimize-autoloader, classmap-authoritative und APCu, für PHP 8.4 und darüber hinaus.

Autoloading-Audit

Analyse von composer.json, Namespace-Struktur und generierten ClassLoader-Dateien

Performance-Tuning

optimize-autoloader, classmap-authoritative und apcu-autoloader korrekt konfigurieren

PHP-8.4-Beratung

Strict Types, Constructor Property Promotion und moderne PSR-Standards im Projekt etablieren