Semaine 4 - Jour 3 : Namespaces et Autoload

Aujourd'hui, nous apprenons à organiser notre code PHP avec les namespaces et à charger automatiquement nos classes avec l'autoloading, en suivant le standard PSR-4.

1. Pourquoi les Namespaces ?

Le problème : Conflits de noms

<?php
// Fichier1.php
class Database {
    public function connect() {
        return "Connexion MySQL";
    }
}

// Fichier2.php (librairie externe)
class Database { // ❌ ERREUR : Classe déjà déclarée !
    public function connect() {
        return "Connexion PostgreSQL";
    }
}
?>

Problème : Impossible d'avoir deux classes avec le même nom dans le même projet !

Solution : Les Namespaces

<?php
// src/MonApp/Database.php
namespace MonApp;

class Database {
    public function connect() {
        return "Connexion MySQL";
    }
}

// vendor/Librairie/Database.php
namespace Librairie;

class Database { // ✅ OK : Namespace différent !
    public function connect() {
        return "Connexion PostgreSQL";
    }
}
?>

2. Déclarer et utiliser des Namespaces

Syntaxe de base

<?php
// src/Models/Utilisateur.php

// Déclarer le namespace (TOUJOURS en premier, après <?php)
namespace Models;

class Utilisateur {
    private $nom;

    public function __construct($nom) {
        $this->nom = $nom;
    }

    public function getNom() {
        return $this->nom;
    }
}
?>

Utiliser une classe avec namespace

<?php
// index.php

require 'src/Models/Utilisateur.php';

// Méthode 1 : Nom complet qualifié (FQCN)
$user1 = new \Models\Utilisateur("Jean");

// Méthode 2 : Utiliser 'use' pour importer
use Models\Utilisateur;

$user2 = new Utilisateur("Marie");

// Méthode 3 : Utiliser un alias
use Models\Utilisateur as User;

$user3 = new User("Paul");

echo $user1->getNom() . "<br>";
echo $user2->getNom() . "<br>";
echo $user3->getNom();
?>

Résultat :

Jean
Marie
Paul

3. Organisation du code avec Namespaces

Structure recommandée

projet/

├── src/
│  ├── Controllers/
│  │  ├── HomeController.php      // namespace Controllers;
│  │  └── UserController.php      // namespace Controllers;
│  │
│  ├── Models/
│  │  ├── User.php          // namespace Models;
│  │  └── Article.php         // namespace Models;
│  │
│  ├── Views/
│  │  └── home.php
│  │
│  └── Database/
│      ├── Connection.php         // namespace Database;
│      └── QueryBuilder.php        // namespace Database;

├── public/
│  └── index.php

└── vendor/                        // Bibliothèques tierces (Composer)

Exemple complet avec sous-namespaces

<?php
// src/Models/User.php
namespace Models;

class User {
    public $nom;
}

// src/Controllers/UserController.php
namespace Controllers;

use Models\User; // Importer la classe User

class UserController {
    public function index() {
        $user = new User();
        $user->nom = "Jean Dupont";
        return $user;
    }
}

// public/index.php
use Controllers\UserController;

$controller = new UserController();
$user = $controller->index();
echo $user->nom;
?>

4. Autoloading avec spl_autoload_register()

Le problème des require multiples

<?php
// ❌ MAUVAIS : Trop de require manuels !
require 'src/Models/User.php';
require 'src/Models/Article.php';
require 'src/Models/Comment.php';
require 'src/Controllers/HomeController.php';
require 'src/Controllers/UserController.php';
// ... et 50 autres fichiers
?>

Solution : Autoloader automatique

<?php
// autoload.php - Charger automatiquement les classes

spl_autoload_register(function ($class) {
    // Exemple : $class = "Models\User"

    // Remplacer les \ par / pour le chemin de fichier
    $class = str_replace('\\', '/', $class);
    // Résultat : "Models/User"

    // Construire le chemin du fichier
    $file = __DIR__ . '/src/' . $class . '.php';
    // Résultat : "/chemin/projet/src/Models/User.php"

    // Charger le fichier s'il existe
    if (file_exists($file)) {
        require $file;
    }
});

// Maintenant, plus besoin de require !
use Models\User;
use Controllers\UserController;

$user = new User(); // ✅ Chargé automatiquement !
$controller = new UserController(); // ✅ Chargé automatiquement !
?>

5. PSR-4 : Standard d'autoloading

Qu'est-ce que PSR-4 ?

PSR-4 (PHP Standards Recommendation 4) est un standard qui définit comment organiser vos classes et namespaces.

Règle simple : Le namespace doit correspondre à la structure des dossiers.

Namespace Chemin du fichier
Models\User src/Models/User.php
Controllers\UserController src/Controllers/UserController.php
Database\MySQL\Connection src/Database/MySQL/Connection.php

Autoloader conforme PSR-4

<?php
// autoload-psr4.php

spl_autoload_register(function ($class) {
    // Préfixe de namespace de base
    $prefix = '';

    // Répertoire de base pour le préfixe de namespace
    $baseDir = __DIR__ . '/src/';

    // Obtenir le nom de classe relatif
    $relativeClass = $class;

    // Remplacer le namespace par le séparateur de répertoire
    $file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';

    // Si le fichier existe, le charger
    if (file_exists($file)) {
        require $file;
    }
});
?>

6. Introduction à Composer

Qu'est-ce que Composer ?

Gestionnaire de dépendances : Composer installe et gère les bibliothèques PHP de votre projet, comme npm pour Node.js.

Autoloader intégré : Composer génère automatiquement un autoloader PSR-4 pour vous ! Plus besoin d'écrire votre propre autoloader.

Fichier composer.json

{
    "name": "monprojet/monapp",
    "description": "Mon application PHP",
    "autoload": {
        "psr-4": {
            "": "src/"
        }
    },
    "require": {
        "php": ">=7.4"
    }
}

Utiliser l'autoloader de Composer

<?php
// public/index.php

// Charger l'autoloader généré par Composer
require_once __DIR__ . '/../vendor/autoload.php';

// Maintenant toutes vos classes sont chargées automatiquement !
use Models\User;
use Controllers\UserController;

$user = new User();
$controller = new UserController();
?>

Commandes Composer essentielles :

  • composer install : Installer les dépendances
  • composer require vendor/package : Ajouter une bibliothèque
  • composer dump-autoload : Régénérer l'autoloader
  • composer update : Mettre à jour les dépendances

7. Exemple complet

Structure du projet

monprojet/

├── src/
│  ├── Models/
│  │  └── User.php             // namespace Models;
│  ├── Controllers/
│  │  └── UserController.php    // namespace Controllers;
│  └── Database/
│      └── Connection.php        // namespace Database;

├── public/
│  └── index.php

├── autoload.php
└── composer.json

Code complet

<?php
// autoload.php
spl_autoload_register(function ($class) {
    $file = __DIR__ . '/src/' . str_replace('\\', '/', $class) . '.php';
    if (file_exists($file)) {
        require_once $file;
    }
});

// public/index.php
require_once __DIR__ . '/../autoload.php';

use Controllers\UserController;
use Database\Connection;

$controller = new UserController();
$user = $controller->show(1);

echo "Utilisateur : " . htmlspecialchars($user->getNom()) . "<br>";

$db = new Connection();
echo $db->connect();
?>

Résultat :

Utilisateur : Jean Dupont
Connexion établie
Froggiesplaining :


Objectifs de ce cours :
✅ Comprendre le problème des conflits de noms de classes
✅ Déclarer et utiliser des namespaces
✅ Organiser le code selon le standard PSR-4
✅ Créer un autoloader avec spl_autoload_register()
✅ Utiliser Composer pour l'autoloading automatique

Points clés à retenir :
Namespaces = Quartiers de la mare (MareNord\Froggie vs MareSud\Froggie)
use = Raccourci pour importer une classe sans écrire le chemin complet
Autoloading = Majordome magique qui charge les classes automatiquement
PSR-4 = Standard qui fait correspondre namespace et structure de dossiers
spl_autoload_register() = Fonction PHP pour créer un autoloader custom
Composer = Super majordome qui gère tout (classes + bibliothèques tierces)
• Un seul require 'vendor/autoload.php' et tout est chargé automatiquement
• Organisation: namespace Models; dans src/Models/User.php

Exercice pratique :
1. Créer la structure: src/Models/, src/Controllers/, src/Views/
2. Créer Models\User.php avec namespace Models;
3. Créer Controllers\UserController.php avec namespace Controllers;
4. Créer un autoload.php avec spl_autoload_register()
5. Dans index.php, require l'autoload puis use Models\User;
6. Instancier un User sans require manuel du fichier
7. Bonus: Installer Composer et configurer composer.json avec PSR-4
8. Conseil de Froggie: Utilise Composer dès que possible ! C'est comme avoir un GPS dans la mare, tu ne te perds jamais.

Froggie explain

GitHub - eCrea