aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Webontwikkeling

PHP PSR-4 autoloading: namespace naar map mappen

PHP PSR-4 is een autoloading-standaard waarmee je klassen uit het juiste bestand laadt op basis van alleen hun naam, zonder ooit handmatig require aan te roepen. Het kernidee past in één zin: je koppelt een namespace-prefix aan een basismap, en de overige namespace-segmenten komen direct overeen met het mappad. In dit artikel behandelen we de regels van PSR-4, hoe je het configureert via composer.json en hoe je de typische fouten uit de dagelijkse praktijk oplost, allemaal met echte voorbeelden.

Waarom is autoloading nodig?

In de begindagen van PHP moest je het bestand van elke klasse handmatig includen voordat je hem gebruikte. In een middelgroot project liep de bovenkant van elk bestand vol met tientallen require_once-regels, en één bestand verplaatsen betekende paden stuk voor stuk bijwerken. Autoloading neemt die pijn weg: de eerste keer dat PHP een ongedefinieerde klasse tegenkomt, roept het een geregistreerde callback (de autoloader) aan en laadt het betreffende bestand ter plekke.

De kern van dit mechanisme is de functie spl_autoload_register(). PSR-4 is een gedeeld contract dat definieert hoe de bij die functie geregistreerde autoloader zich moet gedragen. De standaard werd gepubliceerd door de PHP-FIG (Framework Interop Group), en vandaag volgt vrijwel het hele moderne ecosysteem, waaronder Laravel, Symfony en Guzzle, hem. Daardoor kunnen verschillende libraries één autoloader delen, en wordt het afleiden van een bestandspad uit een klassenaam volledig voorspelbaar.

De kernregel van PSR-4

Volgens PSR-4 bestaat een volledig gekwalificeerde klassenaam uit drie delen: een namespace-prefix, tussenliggende namespaces en de klassenaam. Laten we een voorbeeld bekijken. Stel dat je deze mapping definieert: de prefix App\ is gekoppeld aan de map src/. Dan:

  • klasse App\Mailersrc/Mailer.php
  • klasse App\Services\Invoicesrc/Services/Invoice.php
  • App\Http\Controllers\HomeControllersrc/Http/Controllers/HomeController.php

De werking is eenvoudig: de namespace-prefix (hier App\) wordt vervangen door de basismap (src/); elke resterende namespace-scheider (\) wordt een mapscheider (/); en aan het eind komt .php. Drie punten verdienen aandacht:

  • De mapping is hoofdlettergevoelig. Het bestand voor App\Mailer moet Mailer.php heten, niet mailer.php. Dit is vooral van belang op Linux-servers; macOS/Windows vergeven het lokaal, maar in productie breekt het.
  • De bestandsnaam moet exact hetzelfde zijn als de klassenaam erin.
  • De prefix moet overeenkomen met een basismap; de prefix zelf is geen mapnaam, hij verwijst rechtstreeks naar die map.

PSR-4 configureren met composer.json

In de praktijk schrijf je je eigen autoloader niet met de hand; je gebruikt degene die Composer genereert. Je hoeft alleen je PSR-4-mapping toe te voegen aan de autoload-sectie van composer.json:

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

Let op dat de backslash in JSON ge-escaped wordt (App\\). Je kunt ook meerdere prefixen definiëren; applicatiecode scheiden van testcode is gangbaar:

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    }
}

Hier komt autoload-dev alleen in werking tijdens ontwikkeling; bij installatie voor productie met composer install --no-dev wordt de test-namespace niet geladen. Na het toevoegen of wijzigen van een mapping moet je de autoload-map opnieuw genereren:

composer dump-autoload

Dit commando ververst de maps onder vendor/composer/. Je hoeft het alleen uit te voeren als je een nieuwe PSR-4-prefix toevoegt of de namespace-structuur wijzigt; een nieuwe klasse toevoegen aan een bestaande namespace vereist geen dump, omdat PSR-4 het bestand uit het pad afleidt.

Gebruik: een entrypoint van één regel

Zodra de mapping klaar is, hoef je in het entrypoint van je project (bijvoorbeeld public/index.php) alleen de door Composer gegenereerde autoloader te includen:

require __DIR__ . '/../vendor/autoload.php';

use App\Services\Invoice;
use App\Mailer;

$invoice = new Invoice();
$mailer  = new Mailer();

Nu laden zowel je eigen klassen als alle geïnstalleerde packages zodra hun naam wordt aangeroepen. Het klassebestand zelf moet beginnen met een namespace-declaratie; src/Services/Invoice.php ziet er bijvoorbeeld zo uit:

<?php

namespace App\Services;

class Invoice
{
    public function total(): float
    {
        return 0.0;
    }
}

De regel namespace App\Services; moet volledig consistent zijn met de plaats van het bestand in de PSR-4-mapping. Een mismatch is de meest voorkomende oorzaak van de fout "Class not found".

Het verschil tussen psr-4, classmap en files

Composer ondersteunt drie verschillende autoload-strategieën, en weten wanneer je welke gebruikt maakt het leven makkelijker:

  • psr-4: Koppelt een namespace aan een map en leidt het bestand af uit het pad. De standaardkeuze voor moderne code; een nieuwe klasse toevoegen vereist geen dump.
  • classmap: Scant de opgegeven mappen en schrijft het directe bestandspad van elke klasse in een map. Handig voor legacy-code die de namespace-conventie niet volgt, maar vereist dump-autoload telkens als er een klasse bij komt.
  • files: Laadt bij elke request onvoorwaardelijk bestanden met functiedefinities (geen klassen). Doorgaans gebruikt voor globale helper-functies.

Voor de meeste projecten volstaat psr-4 alleen. classmap en files komen vooral in beeld bij het integreren van oudere libraries zonder namespace.

Autoload-optimalisatie in productie

PSR-4 is flexibel, maar die flexibiliteit kost iets: tijdens runtime berekent PHP het bestandspad uit de klassenaam en controleert of het bestand op schijf bestaat. In productie kun je dit versnellen door het vooraf te berekenen:

composer dump-autoload --optimize

Dit commando (korte vorm -o) scant alle PSR-4-klassen en zet ze om in een classmap, waarmee bestandsopzoekingen tijdens runtime verdwijnen. Meestal gebruik je deze combinatie in de deploystap:

composer install --no-dev --optimize-autoloader

Eén kanttekening: een geoptimaliseerde classmap is statisch. Voeg je in productie een nieuw klassebestand toe, dan wordt de nieuwe klasse niet gevonden totdat je de dump opnieuw uitvoert. Daarom is de optimize-vlag bedoeld voor deployment, niet voor de ontwikkelomgeving.

Veelgestelde vragen

Ik krijg een "Class not found"-fout, waar moet ik kijken?

Controleer eerst drie dingen: is de namespace-declaratie in het bestand consistent met de PSR-4-mapping, is de bestandsnaam exact gelijk aan de klassenaam inclusief hoofdletters, en klopt de basismap in composer.json. Heb je een nieuwe prefix toegevoegd, vergeet dan niet composer dump-autoload uit te voeren. Verschijnt de fout alleen in productie, dan is het bijna altijd een hoofdletterverschil; het Linux-bestandssysteem is hoofdlettergevoelig.

Wat is het verschil tussen PSR-4 en PSR-0?

PSR-0 is de oudere standaard en strikter: het interpreteert underscores (_) in de namespace als mapscheiders en weerspiegelt de hele prefix in de mapstructuur. PSR-4 koppelt de prefix juist rechtstreeks aan een basismap, waardoor je plattere, schonere mapstructuren kunt bouwen. PSR-0 is inmiddels verouderd (deprecated); geef in nieuwe projecten altijd de voorkeur aan PSR-4.

Moet ik voor elke nieuwe klasse dump-autoload uitvoeren?

Nee. Omdat PSR-4 het bestand uit de namespace afleidt, vereist een nieuwe klasse toevoegen aan een bestaande mapping geen extra commando; de klasse werkt meteen. dump-autoload is alleen nodig als je een nieuwe PSR-4-prefix toevoegt, een classmap gebruikt of optimaliseert voor productie.

Is de autoload-opzet in je PHP-project een warboel geworden? Heb je hulp nodig met namespace-organisatie, "class not found"-fouten, het migreren van legacy-code naar PSR-4 of de schone architectuur van een project op basis van Laravel/Symfony, neem dan contact met me op — laten we je codebase samen op een stevige basis zetten.

Bu kategorideki tüm yazılar →

Devamı için