Aller au contenu principal
PHP

Namespaces, Autoloading et Composer en PHP : Guide Complet pour Débutants

person Jean-Luc SALLARSAIB calendar_today 30 janv. 2026 schedule 6 min de lecture visibility 5 vues

Quand votre projet PHP passe de 5 fichiers à 50, le chaos s'installe vite. Comment organiser tout ça ? Comment éviter les conflits de noms ? Comment charger les classes automatiquement ? Ce guide vous accompagne pas à pas.

Le problème : un projet qui grandit

Au début, tout va bien. Vous avez quelques fichiers :

mon-projet/
├── index.php
├── User.php
├── Product.php
└── Database.php

Puis le projet grandit. Vous ajoutez des fonctionnalités. Soudain, vous avez :

mon-projet/
├── index.php
├── User.php
├── UserController.php
├── UserService.php
├── UserRepository.php
├── Product.php
├── ProductController.php
├── ... (50 autres fichiers)

Deux problèmes apparaissent :

  • C'est le bazar : impossible de trouver rapidement un fichier
  • Conflits de noms : que faire si vous avez deux classes User différentes ?

La solution : les namespaces

Un namespace (espace de noms), c'est comme un nom de famille pour vos classes. Deux personnes peuvent s'appeler "Marie", mais "Marie Dupont" et "Marie Martin" sont bien distinctes.

Déclarer un namespace

Créons une structure organisée :

src/
├── User/
│   ├── User.php
│   ├── UserController.php
│   └── UserService.php
└── Product/
    ├── Product.php
    └── ProductController.php

Dans src/User/User.php :

<?php

namespace App\User;  // On déclare le namespace

class User
{
    private string $name;
    private string $email;
    
    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }
    
    public function getName(): string
    {
        return $this->name;
    }
}

Dans src/Product/Product.php :

<?php

namespace App\Product;  // Namespace différent

class Product
{
    private string $name;
    private float $price;
    
    public function __construct(string $name, float $price)
    {
        $this->name = $name;
        $this->price = $price;
    }
}

Règle d'or : Le namespace correspond au chemin du fichier. App\User\User = src/User/User.php

Utiliser une classe avec son namespace

Il existe deux façons d'utiliser une classe :

1. Le nom complet (FQCN - Fully Qualified Class Name)

<?php

// On utilise le chemin complet
$user = new \App\User\User('Jean', 'jean@example.com');
$product = new \App\Product\Product('Clavier', 49.99);

C'est verbeux et pénible. Heureusement, il y a mieux.

2. Le mot-clé use (recommandé)

<?php

namespace App\Shop;

use App\User\User;           // On "importe" la classe
use App\Product\Product;

class Cart
{
    private User $user;
    private array $products = [];
    
    public function __construct(User $user)
    {
        $this->user = $user;
    }
    
    public function addProduct(Product $product): void
    {
        $this->products[] = $product;
    }
}

Le code est maintenant lisible et les classes bien identifiées.

Gérer les conflits de noms avec les alias

Imaginez deux classes User différentes :

<?php

namespace App\Admin;

use App\User\User;                    // User classique
use App\Admin\User as AdminUser;      // User admin avec un alias

class Dashboard
{
    public function showUser(User $user): void
    {
        // Utilisateur normal
    }
    
    public function showAdmin(AdminUser $admin): void
    {
        // Administrateur
    }
}

Le problème du chargement des fichiers

Avec des namespaces, vous avez des fichiers partout. Comment les charger ? La méthode naïve :

<?php
// index.php

require_once 'src/User/User.php';
require_once 'src/User/UserController.php';
require_once 'src/User/UserService.php';
require_once 'src/Product/Product.php';
require_once 'src/Product/ProductController.php';
// ... 50 lignes de require

C'est un cauchemar à maintenir. Chaque nouvelle classe = une ligne à ajouter.

L'autoloading : le chargement automatique

L'autoloading charge automatiquement les fichiers quand PHP rencontre une classe inconnue.

Autoloading manuel (pour comprendre)

<?php
// autoload.php

spl_autoload_register(function (string $className) {
    // App\User\User devient src/User/User.php
    $file = str_replace('\\', '/', $className) . '.php';
    $file = str_replace('App/', 'src/', $file);
    
    if (file_exists($file)) {
        require_once $file;
    }
});

Utilisation :

<?php
// index.php

require_once 'autoload.php';  // Un seul require !

use App\User\User;
use App\Product\Product;

$user = new User('Jean', 'jean@example.com');  // Chargé automatiquement
$product = new Product('Souris', 29.99);       // Chargé automatiquement

Ça fonctionne, mais c'est fragile. Heureusement, il existe un outil professionnel.

Composer : la solution professionnelle

Composer est le gestionnaire de dépendances PHP. Mais même sans dépendances externes, il gère parfaitement l'autoloading.

Installation de Composer

# Sur Linux/Mac
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

# Vérifier l'installation
composer --version

Créer le fichier composer.json

À la racine de votre projet, créez composer.json :

{
    "name": "mon/projet",
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

Cette configuration dit : "Tout ce qui commence par App\ se trouve dans le dossier src/".

Générer l'autoloader

composer dump-autoload

Composer crée un dossier vendor/ avec un fichier autoload.php optimisé.

Utilisation finale

<?php
// index.php

require_once __DIR__ . '/vendor/autoload.php';  // Une seule ligne !

use App\User\User;
use App\Product\Product;
use App\Shop\Cart;

// Tout se charge automatiquement
$user = new User('Marie', 'marie@example.com');
$product = new Product('Écran', 299.99);

$cart = new Cart($user);
$cart->addProduct($product);

PSR-4 : la convention à suivre

PSR-4 est le standard d'autoloading de PHP. Les règles sont simples :

  • Un namespace = un dossier
  • Une classe = un fichier
  • Le nom du fichier = le nom de la classe + .php

Exemple concret :

src/
├── User/
│   ├── User.php              # namespace App\User; class User
│   ├── UserController.php    # namespace App\User; class UserController
│   └── Repository/
│       └── UserRepository.php # namespace App\User\Repository; class UserRepository
└── Product/
    └── Product.php           # namespace App\Product; class Product

Exemple complet : une mini-application

Créons une structure de projet complète :

mon-projet/
├── composer.json
├── public/
│   └── index.php
└── src/
    ├── Entity/
    │   └── User.php
    ├── Repository/
    │   └── UserRepository.php
    └── Service/
        └── UserService.php

composer.json

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

src/Entity/User.php

<?php

namespace App\Entity;

class User
{
    public function __construct(
        private int $id,
        private string $name,
        private string $email
    ) {}
    
    public function getId(): int { return $this->id; }
    public function getName(): string { return $this->name; }
    public function getEmail(): string { return $this->email; }
}

src/Repository/UserRepository.php

<?php

namespace App\Repository;

use App\Entity\User;

class UserRepository
{
    private array $users = [];
    
    public function __construct()
    {
        // Données de test
        $this->users = [
            1 => new User(1, 'Alice', 'alice@example.com'),
            2 => new User(2, 'Bob', 'bob@example.com'),
        ];
    }
    
    public function find(int $id): ?User
    {
        return $this->users[$id] ?? null;
    }
    
    public function findAll(): array
    {
        return $this->users;
    }
}

src/Service/UserService.php

<?php

namespace App\Service;

use App\Repository\UserRepository;
use App\Entity\User;

class UserService
{
    public function __construct(
        private UserRepository $repository
    ) {}
    
    public function getUserById(int $id): ?User
    {
        return $this->repository->find($id);
    }
    
    public function getAllUsers(): array
    {
        return $this->repository->findAll();
    }
}

public/index.php

<?php

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

use App\Repository\UserRepository;
use App\Service\UserService;

// Tout se charge automatiquement !
$repository = new UserRepository();
$service = new UserService($repository);

// Récupérer un utilisateur
$user = $service->getUserById(1);
if ($user) {
    echo "Utilisateur trouvé : " . $user->getName() . "\n";
}

// Lister tous les utilisateurs
foreach ($service->getAllUsers() as $user) {
    echo "- " . $user->getName() . " (" . $user->getEmail() . ")\n";
}

Commandes Composer essentielles

# Générer/mettre à jour l'autoloader
composer dump-autoload

# Optimiser pour la production
composer dump-autoload --optimize

# Installer les dépendances (si vous en ajoutez)
composer install

# Mettre à jour les dépendances
composer update

Récapitulatif

  • Namespaces : organisent vos classes et évitent les conflits
  • use : importe une classe pour l'utiliser sans le chemin complet
  • PSR-4 : namespace = dossier, classe = fichier
  • Composer : gère l'autoloading automatiquement
  • vendor/autoload.php : un seul require pour tout charger

Avec ces bases, vous pouvez maintenant créer des projets PHP bien structurés, maintenables et professionnels.

Partager cet article