Le problème : trop de classes, des noms qui se cognent
Dans un vrai projet, tu as des dizaines de classes, plus celles de bibliothèques tierces. Tôt ou tard, deux Client existent (le tien et celui d'une librairie). Sans organisation, c'est la collision de noms : PHP ne sait plus de laquelle tu parles.
Les namespaces (espaces de noms) règlent ça : ils rangent les classes dans des « dossiers logiques ». Boutique\Client et Facturation\Client cohabitent sans conflit.
Déclarer et utiliser un namespace
// fichier src/Boutique/Produit.php
namespace Boutique;
class Produit {
public function __construct(public string $nom) {}
}
// ailleurs, pour s'en servir :
use Boutique\Produit; // on "importe" le nom
$p = new Produit("Café"); // au lieu de new \Boutique\Produit("Café")
Convention : le namespace reflète l'arborescence des dossiers (Boutique\Produit ↔ src/Boutique/Produit.php). C'est la base de l'autoloading.
L'autoloading : charger les classes toutes seules
Sans autoloading, il faudrait un require manuel pour chaque fichier de classe — ingérable. L'autoloading charge le bon fichier automatiquement la première fois qu'une classe est utilisée, en se basant sur son namespace.
Le standard s'appelle PSR-4, et l'outil universel, c'est Composer (le gestionnaire de dépendances de PHP). En pratique :
// composer.json : on mappe un préfixe de namespace à un dossier
{
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
// puis, une seule ligne en tête du projet :
require 'vendor/autoload.php';
// et c'est tout : new App\Boutique\Produit() charge src/Boutique/Produit.php tout seul
Tu n'apprends pas Composer par cœur : retiens la logique. Un namespace = un chemin de dossier, et l'autoloader traduit le nom de la classe en chemin de fichier. Si tu comprends ça, tu sauras toujours où ranger (et retrouver) une classe.
Exécute : deux namespaces, zéro collision
Ici, deux classes pourraient s'appeler pareil : leur namespace les distingue. (On utilise la syntaxe à blocs pour tout mettre dans un seul fichier exécutable.)
<?php
namespace Boutique {
class Client { public function bonjour(): string { return "Client de la boutique"; } }
}
namespace Facturation {
class Client { public function bonjour(): string { return "Client de la facturation"; } }
}
namespace { // espace global
$a = new \Boutique\Client();
$b = new \Facturation\Client();
echo $a->bonjour() . "\n"; // Client de la boutique
echo $b->bonjour() . "\n"; // Client de la facturation
echo get_class($b) . "\n"; // Facturation\Client
}
?>
Sans remonter dans la leçon : à quoi sert un namespace, et quelle est la règle PSR-4 qui lie App\Boutique\Produit à un fichier sur le disque ?
Client peuvent coexister). En PSR-4, le namespace reflète l'arborescence : avec le mapping "App\\": "src/", la classe App\Boutique\Produit est chargée depuis src/Boutique/Produit.php. L'autoloader traduit le nom complet en chemin de fichier.Ton composer.json mappe "App\\": "src/". L'IA te donne ce fichier de classe. Ton rôle de relecteur : l'accepter tel quel ou le rejeter, et dire pourquoi.
// fichier : src/Boutique/Produit.php
namespace App\Models;
class Produit {
public function __construct(public string $nom) {}
}
App\Models ne correspond pas au chemin src/Boutique/ : PSR-4 attend la classe App\Models\Produit dans src/Models/Produit.php. Avec ce mapping, l'autoloader cherchera au mauvais endroit et lèvera une « class not found ». Le code compile en isolé, mais il casse dès que Composer essaie de le charger. Corriger en namespace App\Boutique; (ou déplacer le fichier dans src/Models/).Classes, visibilité, héritage, interfaces, traits, namespaces : tu as toute la POO PHP en main. Ce sont exactement les briques sur lesquelles reposent Laravel, Symfony et tout le PHP moderne.
Revoir le cours →The problem: too many classes, names clashing
In a real project, you have dozens of classes, plus third-party libraries. Sooner or later, two Client classes exist (yours and a library's). Without organization, that's a name collision: PHP no longer knows which one you mean.
Namespaces fix this: they file classes into "logical folders". Boutique\Client and Facturation\Client coexist without conflict.
Declaring and using a namespace
// file src/Boutique/Produit.php
namespace Boutique;
class Produit {
public function __construct(public string $nom) {}
}
// elsewhere, to use it:
use Boutique\Produit; // we "import" the name
$p = new Produit("Coffee"); // instead of new \Boutique\Produit("Coffee")
Convention: the namespace mirrors the folder tree (Boutique\Produit ↔ src/Boutique/Produit.php). That's the basis of autoloading.
Autoloading: loading classes automatically
Without autoloading, you'd need a manual require for each class file — unmanageable. Autoloading loads the right file automatically the first time a class is used, based on its namespace.
The standard is called PSR-4, and the universal tool is Composer (PHP's dependency manager). In practice:
// composer.json: map a namespace prefix to a folder
{
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
// then, a single line at the top of the project:
require 'vendor/autoload.php';
// and that's it: new App\Boutique\Produit() loads src/Boutique/Produit.php by itself
You don't learn Composer by heart: remember the logic. A namespace = a folder path, and the autoloader translates the class name into a file path. Understand that, and you'll always know where to put (and find) a class.
Run it: two namespaces, zero collision
Here, two classes could have the same name: their namespace tells them apart. (We use the block syntax to fit everything in one runnable file.)
<?php
namespace Boutique {
class Client { public function bonjour(): string { return "Shop client"; } }
}
namespace Facturation {
class Client { public function bonjour(): string { return "Billing client"; } }
}
namespace { // global space
$a = new \Boutique\Client();
$b = new \Facturation\Client();
echo $a->bonjour() . "\n"; // Shop client
echo $b->bonjour() . "\n"; // Billing client
echo get_class($b) . "\n"; // Facturation\Client
}
?>
Classes, visibility, inheritance, interfaces, traits, namespaces: you've got all of PHP OOP in hand. These are exactly the bricks Laravel, Symfony and all modern PHP are built on.
Back to the course →Tu sais désormais structurer un vrai projet PHP objet : classes, visibilité, héritage, interfaces, traits et namespaces. Le même état d'esprit existe côté navigateur : direction JavaScript avancé, avec ses classes, ses modules et les API du navigateur.
JavaScript avancé →