3.3Namespaces, autoloading & Composer
The essentials in 30 seconds
- Namespaces prevent collisions: namespace App\Models; at the top, use to import — two User classes coexist in different spaces.
- Autoloading removes inclusions: PSR-4 convention (namespace → directories/files), the class loads on first use.
- Composer connects to the ecosystem: composer.json declares, composer install downloads into vendor/ (not versioned) + autoloader, composer.lock pins.
Running case — Riad escapes require hell
Riad, web developer in Constantine, juggles forty manual requires and a collision between his Email class and a sending library's. He tidies his classes into App\Shop namespaces, adopts PSR-4 autoloading (namespace = file path), initializes Composer, installs the library via composer require and now loads only a single require 'vendor/autoload.php'. No more inclusions, no more collisions.
This same case returns in the lesson, the diagram, the script and the 48h challenge.
1. Namespaces and PSR-4 autoloading
As the project grows, two problems: name conflicts (two User classes) and unmanageable manual inclusions. Namespaces organise classes into logical spaces, like folders: App\Models\User and Vendor\Auth\User coexist. Declare at the top (namespace App\Models;) and import with use App\Models\User;.
Autoloading automatically loads a class's file on first use, via the PSR-4 convention: the namespace matches the directory/file structure (App\Models\User → src/Models/User.php). No more require lists: Riad no longer includes anything by hand, the autoloader finds the right file alone.
2. Composer: dependencies and ecosystem
Composer is PHP's dependency manager (the npm equivalent): you declare in composer.json, composer install downloads into vendor/ and generates the autoloader (require 'vendor/autoload.php'; loads everything). It gives access to Packagist, a huge repository of proven libraries (email, PDF, HTTP) — install instead of recoding.
As with npm: do NOT version vendor/ (regenerable via install) and composer.lock pins exact versions (reproducibility). Riad remembers the node_modules/package-lock parallel: same discipline, same reflexes. All frameworks (Laravel, Symfony) rest on this foundation.
🔎 Concrete example — Namespace, PSR-4 and Composer autoloader
Riad organises his class and loads everything in one line.
email; }
}
// entry point: a single load
require 'vendor/autoload.php';
use App\Modeles\Utilisateur;
$client = new Utilisateur('riad@fictitious-example.test');
Reading: declared namespace, single autoloader, import via use, direct instantiation.
Lesson: no manual require of the class file — the convention makes the link.
Section vocabulary
- Namespaces
- Logical spaces organising classes and preventing conflicts; namespace declaration at the top, import with use.
Simple example: App\Models\User vs Vendor\Auth\User at Riad's.
What it is not: hand-prefixed names to avoid collisions.
Reflex: namespace from the first class of a project.
- Autoloading (PSR-4)
- Automatic loading of a class's file on use, via the namespace → directories/files convention.
Simple example: App\Models\User found in src/Models/User.php.
What it is not: forty manual requires at the top of a script.
Reflex: strictly follow the PSR-4 convention.
- Composer
- PHP dependency manager: installing libraries, managing versions and autoloader; transformed the ecosystem.
Simple example: Riad's composer require of the sending library.
What it is not: ZIPs downloaded and included by hand.
Reflex: install via Composer, never by hand.
- composer.json / vendor / lock
- composer.json declares; install downloads into vendor/ (not versioned, regenerable) + autoloader; composer.lock pins versions.
Simple example: The committed lock, the ignored vendor/ at Riad's.
What it is not: a committed vendor/ of thousands of files.
Reflex: version json + lock, ignore vendor/.
- Packagist / ecosystem
- PHP package repository: thousands of reusable libraries — install proven code instead of recoding.
Simple example: The SMTP sending library installed in one command.
What it is not: rewriting your own fragile email sending.
Reflex: look for proven code before building in-house.
In practice — Organising and connecting a modern project
- Declare namespaces (`namespace App\Models;`) to organise your classes and avoid conflicts; import with `use`.
- Initialize Composer (`composer init`) and understand PSR-4 autoloading (namespace → directories): no need to include each class.
- Install an external library (`composer require ...`) and use it via the autoloader (`require 'vendor/autoload.php';`).
- Remember: do not version vendor/ (regenerable), composer.lock pins versions — like node_modules/package-lock for npm.
Ready-to-say script — presenting your structured project (30 s)
“The project is namespaced under App, in PSR-4: each class autoloads. Dependencies go through Composer, installed in non-versioned vendor, versions pinned by the lock. A single require of the autoloader at entry.”
Say in review; show the tree and the composer.json.
Copy-paste template — minimal PSR-4 composer.json
{
"name": "riad/boutique",
"require": {
"php": ">=8.1"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
// Then: composer install
// Entry: require 'vendor/autoload.php';
Independent
One PSR-4 composer.json is enough to tidy quote classes.
SME in Constantine
Riad namespaces the shop by module so two teams code without collision.
Product team
Enforce PSR-4 + committed lock for reproducible installs everywhere.
Beginner
This week: one namespace, two autoloaded classes, zero manual requires.
✓ Best practices
- Namespace from the start (avoid future collisions).
- Follow PSR-4 to the letter (namespace = file path).
- Install proven code via Composer rather than recoding.
✗ Common pitfalls
- Versioning vendor/ (polluted repo, binary conflicts).
- Including classes by hand instead of the autoloader.
- Forgetting the lock (floating versions, non-reproducible installs).
Key takeaways
- NAMESPACES: conflict-free logical spaces (two Users coexist). namespace + use to import.
- AUTOLOADING (PSR-4): automatic loading via the namespace → directories convention. No more manual inclusions.
- COMPOSER = DEPENDENCY manager (like npm): install, version, generate the autoloader. composer.json, vendor/ (not versioned), composer.lock (pinned).
- FOUNDATION of modern, professional PHP (all frameworks): organise big projects, autoload, tap into Packagist.
48h challenge — apply tomorrow
Namespace 2 PSR-4 classes loaded by 1 autoloader, then install 1 library via Composer.
- I declare and import namespaces without hesitation.
- My classes load with no manual require.
- My vendor/ is ignored, my lock is committed.
Frequently asked questions
What does Composer really change, and why is it central?
Before Composer: manual downloads, hand inclusions, self-managed versions — a handcrafted ecosystem. After: one-command installation with dependency resolution, access to Packagist (thousands of proven libraries), managed versions (reproducible lock) and a generated autoloader. It is the npm equivalent: the step from handcrafted PHP to professional PHP.
Why do namespaces and autoloading work together?
Namespaces solve conflicts (logical prefix: two Users coexist), autoloading solves inclusions (automatic loading). The link: the PSR-4 convention maps namespace to file path — the autoloader derives the file from the class's full name. Organise (namespaces) + load (autoloading): one clean system.
Which file declares dependencies and PSR-4 autoloading?