Autoloading PSR-4 z Composerem

🎯 Po tej lekcji skonfigurujesz mapowanie namespace → katalog w composer.json, uruchomisz composer dump-autoload i użyjesz vendor/autoload.php zamiast ręcznego spl_autoload_register.

W Module 6 napisałeś własny autoloader przy pomocy spl_autoload_register. Działał dobrze, ale wymagał utrzymania ręcznego mapowania i nie integrował się z bibliotekami zewnętrznymi. Composer rozwiązuje oba problemy — generuje zoptymalizowany autoloader PSR-4 na podstawie jednej sekcji w composer.json.

Konfiguracja PSR-4 w composer.json

Otwórz composer.json i dodaj sekcję autoload:

{
    "name": "twoja-firma/projekt",
    "require": {
        "php": ">=8.1"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

Zapis "App\\": "src/" oznacza:

Klasy z namespace App\ szukaj w katalogu src/.

Konwencja PSR-4 zamienia backslashe namespace na separatory katalogów i dodaje .php:

App\Models\Uzytkownik     →  src/Models/Uzytkownik.php
App\Services\Email        →  src/Services/Email.php
App\Http\Controllers\Home →  src/Http/Controllers/Home.php
⚠️ Podwójny backslash w JSON: Backslash w JSON musi być poprzedzony ukośnikiem ucieczki. Namespace App\ (z ukośnikiem na końcu) zapisujesz w JSON jako "App\\". To nie błąd — tak działa składnia JSON.

composer dump-autoload — generuj autoloader

Po każdej zmianie sekcji autoload w composer.json uruchom:

composer dump-autoload

Composer odczyta konfigurację i wygeneruje pliki w vendor/composer/. Zobaczysz komunikat:

Generating autoload files
Generated autoload files

Możesz też użyć skrótu:

composer dump-autoload --optimize

Flaga --optimize tworzy mapę wszystkich klas do plików (szybsze na produkcji, wolniejsze przy każdym dump-autoload).

require 'vendor/autoload.php'

Po wygenerowaniu autoloadera wystarczy jedna linia na początku każdego skryptu wejściowego:

<?php
declare(strict_types=1);

require 'vendor/autoload.php';

Od tego momentu PHP automatycznie znajdzie każdą klasę z namespace App\ w katalogu src/ — bez żadnych dodatkowych require ani include.

Pełny przykład

Struktura projektu:

projekt/
├── src/
│   ├── Models/
│   │   └── Uzytkownik.php
│   └── Services/
│       └── Email.php
├── vendor/
│   └── autoload.php       ← wygenerowany przez Composer
├── composer.json
└── index.php
<?php
// src/Models/Uzytkownik.php
declare(strict_types=1);
namespace App\Models;

class Uzytkownik
{
    public function __construct(
        public readonly string $imie,
        public readonly string $email,
    ) {}
}
<?php
// src/Services/Email.php
declare(strict_types=1);
namespace App\Services;

use App\Models\Uzytkownik;

class Email
{
    public function wyslij(Uzytkownik $u, string $temat): string
    {
        return "Wysyłam '{$temat}' do {$u->email}";
    }
}
<?php
// index.php
declare(strict_types=1);

require 'vendor/autoload.php'; // to jedyna linia require w całym projekcie

use App\Models\Uzytkownik;
use App\Services\Email;

$uzytkownik = new Uzytkownik('Anna', '[email protected]');
$email      = new Email();

echo $email->wyslij($uzytkownik, 'Witaj w systemie!');
// Wysyłam 'Witaj w systemie!' do [email protected]

Porównanie: ręczny vs Composer

| | Ręczny spl_autoload_register | PSR-4 z Composerem | |---|---|---| | Konfiguracja | Plik PHP z logiką | Kilka linii JSON | | Biblioteki zewnętrzne | Trzeba osobno dołączyć | Automatycznie obsłużone | | Optymalizacja | Ręczna | --optimize | | Standard | Własny | PSR-4 (branżowy) |

💡 Kiedy uruchamiać dump-autoload: Musisz uruchomić composer dump-autoload po każdej zmianie sekcji autoload lub autoload-dev w composer.json. Przy composer require i composer install Composer robi to automatycznie.

Wiele namespace w jednym projekcie

Możesz mapować kilka prefiksów naraz — np. gdy masz osobny namespace dla testów:

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

Sekcja autoload-dev jest ładowana tylko w środowisku deweloperskim (nie na produkcji po composer install --no-dev).

W następnej lekcji zobaczysz, jak zainstalować prawdziwą bibliotekę z Packagist i użyć jej w kodzie.

Sprawdź się

Co robi komenda `composer dump-autoload`?

Jak powinno wyglądać mapowanie PSR-4 dla namespace App\ na katalog src/ w composer.json?

Czego musisz użyć w pliku index.php, żeby klasy projektu były wczytywane automatycznie?

Ćwiczenie

Masz projekt z katalogiem src/ i klasami w namespace App\. Dodaj sekcję autoload PSR-4 do composer.json, uruchom composer dump-autoload i sprawdź, że plik vendor/autoload.php istnieje. Następnie utwórz src/Powitanie.php z klasą App\Powitanie (metoda przywitaj(string $imie): string) i użyj jej w index.php przez require 'vendor/autoload.php'.

Pokaż rozwiązanie
// composer.json — dodaj:
// "autoload": {"psr-4": {"App\\\\": "src/"}}

// W terminalu:
composer dump-autoload

// src/Powitanie.php
<?php
declare(strict_types=1);
namespace App;

class Powitanie
{
    public function przywitaj(string $imie): string
    {
        return "Cześć, {$imie}!";
    }
}

// index.php
<?php
declare(strict_types=1);
require 'vendor/autoload.php';
use App\Powitanie;

$p = new Powitanie();
echo $p->przywitaj('Ania'); // Cześć, Ania!