Développement Web

Composer et l’autoloading PSR-4 en PHP, pas à pas

12 min de lecture

Jusqu’ici, le projet « Atelier » tient dans quelques fichiers que l’on inclut à la main avec require. Cela ne tient pas à l’échelle : chaque nouvelle classe ajoute un require, les chemins en dur cassent au moindre déplacement, et impossible d’utiliser une bibliothèque tierce proprement. Composer résout tout cela. C’est le gestionnaire de dépendances de l’écosystème PHP : il installe des bibliothèques, gère leurs versions, et charge automatiquement vos classes grâce à la norme PSR-4. Dans ce tutoriel, on structure « Atelier » comme un vrai projet et on y branche une bibliothèque de journalisation.

Article de référence : ce tutoriel fait partie du guide complet du PHP moderne. Les classes manipulées ici viennent du tutoriel sur la programmation orientée objet.

Ce que vous allez apprendre

  • Installer Composer et initialiser un projet avec composer.json.
  • Comprendre l’autoloading PSR-4 et mapper un espace de noms vers un dossier.
  • Installer une dépendance tierce et comprendre le rôle de composer.lock.
  • Différencier dépendances de production et de développement.
  • Optimiser l’autoloader pour la mise en production.

Ce que vous allez construire

Une structure de projet propre : un dossier src/ contenant les classes sous l’espace de noms Atelier\, chargées automatiquement, et un point d’entrée public/index.php qui les utilise sans un seul require manuel. On y ajoute Monolog pour journaliser les mouvements de stock.

Prérequis

  • PHP 8.4 en ligne de commande (php --version).
  • Un terminal (PowerShell, bash…) et un accès à Internet pour télécharger les paquets.
  • Les classes Piece, Categorie, DepotPieces et DepotMemoire du tutoriel orienté objet.
  • ⏱️ Temps estimé : ~40 minutes.

Étape 1 — Installer Composer

Composer est un exécutable PHP. La méthode d’installation dépend du système, mais l’idée est la même : récupérer le fichier composer.phar et le rendre accessible globalement. Sous Windows, le plus simple est l’installeur officiel Composer-Setup.exe depuis getcomposer.org, qui détecte PHP et configure le PATH. Sous Linux ou macOS, on télécharge et on installe en quelques commandes.

# Linux / macOS : installation officielle
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
sudo mv composer.phar /usr/local/bin/composer
php -r "unlink('composer-setup.php');"

# Vérifier
composer --version

La commande composer --version doit afficher quelque chose comme « Composer version 2.x.x » (la branche 2 est la seule maintenue ; au moment d’écrire, la dernière est la 2.10). Si le terminal ne reconnaît pas composer, c’est un problème de PATH : sous Windows, rouvrez le terminal après l’installeur ; sous Linux, vérifiez que /usr/local/bin est dans votre PATH. Composer a besoin de PHP en ligne de commande : si php n’est pas trouvé non plus, installez d’abord PHP.

Étape 2 — Initialiser le projet

Un projet Composer est décrit par un fichier composer.json à sa racine. On peut l’écrire à la main, mais composer init le génère en posant quelques questions. Créez un dossier atelier/, placez-vous dedans, et lancez l’initialisation.

mkdir atelier && cd atelier
composer init

L’assistant demande un nom de paquet (au format fournisseur/projet, par exemple atelier/inventaire), une description, un type, et la version minimale de PHP. On peut sauter les questions sur les dépendances pour le moment. À la fin, un composer.json minimal apparaît. Voici à quoi il ressemble une fois complété pour notre besoin :

{
    "name": "atelier/inventaire",
    "description": "Gestion de stock de pièces détachées",
    "type": "project",
    "require": {
        "php": ">=8.4"
    },
    "autoload": {
        "psr-4": {
            "Atelier\\": "src/"
        }
    },
    "config": {
        "sort-packages": true
    }
}

Le bloc require déclare les contraintes : ici, PHP 8.4 ou supérieur. Le bloc autoload est le cœur du sujet : il dit à Composer que toute classe de l’espace de noms Atelier\ se trouve dans le dossier src/. C’est la norme PSR-4, que l’étape suivante détaille. Le double antislash \\ est l’échappement de l’antislash en JSON.

Étape 3 — Comprendre l’autoloading PSR-4

PSR-4 est une convention publiée par le PHP-FIG qui établit une correspondance directe entre le nom pleinement qualifié d’une classe et le chemin de son fichier. La règle est simple : on déclare un préfixe d’espace de noms et le dossier de base correspondant ; ensuite, chaque segment d’espace de noms après le préfixe devient un sous-dossier, et le nom de la classe devient le nom du fichier, avec l’extension .php.

Avec notre mapping "Atelier\\": "src/", voici les correspondances :

Classe pleinement qualifiée Fichier attendu
Atelier\Piece src/Piece.php
Atelier\Categorie src/Categorie.php
Atelier\Depot\DepotMemoire src/Depot/DepotMemoire.php

La contrainte cruciale : le nom de l’espace de noms déclaré dans le fichier doit correspondre à son emplacement. Un fichier src/Depot/DepotMemoire.php doit déclarer namespace Atelier\Depot; et contenir une classe DepotMemoire. Si le dossier, le fichier et le namespace ne s’accordent pas exactement (casse comprise), l’autoloader ne trouvera pas la classe. Réorganisons donc les classes du projet :

atelier/
├── composer.json
├── src/
│   ├── Piece.php          → namespace Atelier;
│   ├── Categorie.php      → namespace Atelier;
│   └── Depot/
│       ├── DepotPieces.php   → namespace Atelier\Depot;
│       └── DepotMemoire.php  → namespace Atelier\Depot;
└── public/
    └── index.php

Après toute modification du bloc autoload ou ajout d’un dossier, on régénère la carte de l’autoloader avec composer dump-autoload. Cette commande crée (ou met à jour) le fichier vendor/autoload.php, qui est le seul fichier à inclure dans votre code pour que toutes vos classes deviennent disponibles.

Point d’étape — Après composer dump-autoload, vous devez voir apparaître un dossier vendor/ contenant autoload.php. Si Composer affiche « Generated autoload files containing 0 classes », vérifiez que vos fichiers sont bien dans src/ et que leur namespace commence par Atelier.

Étape 4 — Utiliser l’autoloader dans le point d’entrée

Le point d’entrée de l’application — le fichier appelé par le serveur web — inclut une seule fois vendor/autoload.php, puis utilise les classes par leur nom. Plus aucun require de classe métier.

<?php
// public/index.php
declare(strict_types=1);

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

use Atelier\Piece;
use Atelier\Categorie;
use Atelier\Depot\DepotMemoire;

$depot = new DepotMemoire();
$depot->ajouter(new Piece('VIS-M6', 'Vis M6', Categorie::Visserie, 250.0, 120));

foreach ($depot->toutes() as $piece) {
    echo $piece->libelle . PHP_EOL;
}

Quand le code rencontre new Piece(...), l’autoloader de Composer intercepte la demande, traduit Atelier\Piece en src/Piece.php, inclut le fichier, et le tour est joué — de façon paresseuse, seulement pour les classes réellement utilisées. Lancez php public/index.php : la pièce s’affiche. Vous venez de supprimer toute la plomberie d’inclusion manuelle. C’est ce mécanisme, invisible et automatique, qui rend possibles les projets de centaines de fichiers.

Étape 5 — Installer une dépendance tierce

Le vrai pouvoir de Composer, c’est l’accès à des dizaines de milliers de bibliothèques publiées sur Packagist, le dépôt central. Ajoutons Monolog, la bibliothèque de journalisation la plus utilisée de l’écosystème, pour tracer les mouvements de stock. On l’installe avec composer require.

composer require monolog/monolog

Cette commande fait plusieurs choses d’un coup : elle cherche la dernière version compatible de Monolog, l’ajoute au bloc require de composer.json, télécharge son code dans vendor/monolog/, télécharge aussi ses propres dépendances, et met à jour l’autoloader pour qu’il connaisse les classes de Monolog. Vous pouvez immédiatement utiliser la bibliothèque :

<?php
// public/index.php (extrait)
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Level;

$log = new Logger('atelier');
$log->pushHandler(new StreamHandler(__DIR__ . '/../var/atelier.log', Level::Info));

$log->info('Pièce ajoutée', ['reference' => 'VIS-M6', 'quantite' => 120]);

Aucune inclusion manuelle des fichiers de Monolog : l’autoloader PSR-4 de Composer s’en occupe, car Monolog déclare lui-même son mapping PSR-4. Le journal s’écrit dans var/atelier.log avec la date, le niveau et le contexte structuré. Cette même bibliothèque sert de fondation au tutoriel sur la gestion des erreurs et des exceptions, où l’on journalise proprement les incidents.

Étape 6 — composer.json contre composer.lock

Deux fichiers gouvernent les dépendances, et la distinction est essentielle. composer.json exprime vos contraintes : « je veux Monolog, série 3 ». composer.lock enregistre les versions exactes réellement installées : « Monolog 3.7.0, avec telles dépendances à telles versions précises ». Le premier dit l’intention, le second fige l’état reproductible.

La conséquence pratique structure tout déploiement. En développement, composer require et composer update résolvent les contraintes et mettent à jour le lock. En production, on ne lance jamais composer update : on exécute composer install, qui lit le composer.lock et installe exactement les versions qui y figurent. Ainsi, la machine de production reçoit précisément ce qui a été testé. Les deux fichiers se committent dans Git ; le dossier vendor/, lui, s’ignore.

# .gitignore
/vendor/
/var/*.log

Étape 7 — Dépendances de développement et optimisation

Certaines bibliothèques ne servent qu’au développement : outils de test, analyseurs statiques. On les sépare avec l’option --dev, ce qui les range dans require-dev. Elles ne seront pas installées en production si l’on passe --no-dev.

# Outil de qualité, uniquement en développement
composer require --dev phpstan/phpstan

# Déploiement en production : sans les outils de dev, autoloader compilé
composer install --no-dev --optimize-autoloader

L’option --optimize-autoloader (ou -o) transforme l’autoloader paresseux en une carte de classes pré-calculée : Composer parcourt tous les fichiers une fois et génère une table associant chaque classe à son chemin. En production, cela évite de deviner le chemin à chaque chargement et accélère sensiblement le démarrage. Combinée à --no-dev, cette commande produit un vendor/ minimal et rapide, exactement ce qu’on veut sur un serveur.

Point d’étape — Lancez composer install --no-dev --optimize-autoloader dans une copie du projet. PHPStan ne doit plus apparaître dans vendor/, et Composer doit signaler « Generating optimized autoload files ». C’est l’état dans lequel votre application doit partir en production.

Étape 8 — Vérification finale

Le projet doit maintenant se lancer avec php public/index.php, charger toutes ses classes sans require explicite, écrire un journal via Monolog, et se déployer en une commande reproductible. Supprimez le dossier vendor/ puis relancez composer install : tout doit se reconstruire à l’identique depuis le composer.lock. Si c’est le cas, votre projet est correctement structuré et reproductible — la condition de base de tout travail d’équipe et de tout déploiement automatisé.

Pièges fréquents

Symptôme / erreur Cause probable Correctif
Class "Atelier\Piece" not found namespace ou chemin non conforme à PSR-4 Aligner dossier, nom de fichier et namespace (casse comprise), puis composer dump-autoload
Could not open input file: composer.phar Composer non installé globalement Réinstaller et vérifier le PATH
Les modifs de classe ne sont pas prises en compte Carte d’autoload optimisée figée Relancer composer dump-autoload (sans -o en développement)
Your requirements could not be resolved Conflit de contraintes de versions Lire le message, assouplir une contrainte ou mettre à jour PHP
Le serveur télécharge tout au démarrage composer install lancé sans lock Committer composer.lock et déployer avec lui

Réalités du terrain

Sur une connexion lente ou facturée au volume, composer install peut peser. Trois habitudes aident. D’abord, committer composer.lock : l’installation devient déterministe et le cache de Composer (dans le dossier personnel) évite de re-télécharger ce qui est déjà connu. Ensuite, en intégration continue ou en déploiement, mettre en cache le dossier ~/.composer/cache entre deux exécutions. Enfin, sur un hébergement mutualisé sans accès SSH, on évite de lancer Composer sur le serveur : on construit le dossier vendor/ en local avec --no-dev -o, puis on téléverse l’ensemble. Le projet tourne alors sans que Composer soit même présent sur l’hébergement.

Récapitulatif

Vous avez transformé un tas de fichiers en un projet structuré. Composer installe et verrouille les dépendances ; l’autoloading PSR-4 charge vos classes par correspondance nom/chemin, supprimant les require manuels ; composer.json exprime les contraintes et composer.lock fige l’état reproductible ; require-dev isole les outils de développement ; et --no-dev --optimize-autoloader prépare un déploiement rapide. C’est l’ossature commune à tous les projets PHP professionnels.

Aide-mémoire

Commande / élément Rôle
composer init Créer un composer.json
composer require vendor/paquet Ajouter une dépendance de production
composer require --dev vendor/paquet Ajouter une dépendance de développement
composer install Installer d’après le composer.lock
composer update Mettre à jour et recalculer le lock (jamais en production)
composer dump-autoload Régénérer l’autoloader
"psr-4": {"Atelier\\": "src/"} Mapper un espace de noms vers un dossier
install --no-dev -o Déploiement de production optimisé

À vous de jouer

Ajoutez un second mapping PSR-4 pour les tests, par exemple "Atelier\\Tests\\": "tests/" dans un bloc autoload-dev, puis créez une classe Atelier\Tests\PieceTest dans tests/PieceTest.php et vérifiez qu’elle se charge.

Voir une solution
// composer.json
"autoload-dev": {
    "psr-4": {
        "Atelier\\Tests\\": "tests/"
    }
}
// puis : composer dump-autoload
// tests/PieceTest.php → namespace Atelier\Tests; class PieceTest {}

Tutoriels liés

Pour aller plus loin

Foire aux questions

Faut-il committer le dossier vendor/ ?

Non, dans la grande majorité des cas. On committe composer.json et composer.lock, et on régénère vendor/ au déploiement avec composer install. Cela garde le dépôt léger et l’historique lisible. L’exception est l’hébergement sans accès SSH, où l’on téléverse vendor/ construit en local.

Quelle différence entre composer install et composer update ?

install installe exactement les versions du composer.lock ; update recalcule les versions selon les contraintes du composer.json et réécrit le lock. On utilise update en développement quand on veut récupérer des mises à jour, et install partout ailleurs, surtout en production.

Comment lire une contrainte de version comme ^3.7 ?

Le caret ^ autorise les mises à jour qui ne cassent pas la compatibilité selon le versionnage sémantique : ^3.7 accepte tout ce qui va de 3.7.0 jusqu’à, mais sans inclure, 4.0.0. C’est le réglage par défaut de composer require, qui équilibre stabilité et correctifs.

Partager