Chapter 11 Β· Going Deeper
Namespaces & Autoloading
Real projects contain dozens or hundreds of classes β yours, plus classes from
libraries. Two problems appear: name collisions ("two classes called User?!") and the pain of
writing require for every single file. Namespaces solve the first; autoloading
solves the second.
Problem 1: two classes with the same name
You wrote a class Mail. You then install a library that also has a class
Mail. PHP refuses: "Cannot redeclare class Mail." Disaster β you can't rename the
library's class.
Two families can each have a child called Chanda without confusion β
because each Chanda has a surname and an address. "Chanda of Banda family, Kabwata" and
"Chanda of Phiri family, Chelstone" are clearly different people. A namespace
is a class's address: App\Models\Student and Library\Reports\Student
can happily coexist.
Declaring a namespace
The first statement of a file declares where its classes live:
src/Models/Student.php<?php
namespace App\Models;
class Student {
public function __construct(public string $name) {}
}
The full name of this class is now App\Models\Student. The backslash
\ separates the levels, like folders on a disk.
Using a namespaced class
Three ways, from clumsy to elegant:
<?php
// 1. The full address every time (works, but tiring)
$s = new \App\Models\Student("Chanda");
// 2. "use" at the top imports the class β then use the short name
use App\Models\Student;
$s = new Student("Chanda");
// 3. Rename on import if two names clash β this fixes our Mail problem!
use App\Models\Student as MyStudent;
use Library\Reports\Student as ReportStudent;
$a = new MyStudent("Chanda");
$b = new ReportStudent("Chanda");
The namespace mirrors the folder path. Class App\Models\Student lives in the
file src/Models/Student.php. One class per file, file named exactly like the class.
This convention is called PSR-4, and it's what makes autoloading possible.
Problem 2: require, require, requireβ¦
Without help, every file must manually load each class it uses:
require "src/Models/Student.php";
require "src/Models/Course.php";
require "src/Services/Enrollment.php";
require "src/Services/Billing.php";
// ...forty more lines of this misery...
Forget one and you get "Class not found". Rename a folder and everything breaks.
The fix: autoloading
An autoloader is a librarian. Instead of you fetching every book you might need before starting your homework, you just start working β and the moment you mention a book you don't have, the librarian silently fetches it from the shelves. PHP lets us register such a librarian: whenever code mentions an unknown class, our function is asked to find and load its file.
autoload.php<?php
spl_autoload_register(function (string $className) {
// Turn App\Models\Student into src/Models/Student.php
$path = str_replace("App\\", "src/", $className); // swap the root
$path = str_replace("\\", "/", $path) . ".php"; // backslashes -> slashes
if (file_exists($path)) {
require $path;
}
});
index.php<?php
require "autoload.php"; // the ONLY require you will ever write
use App\Models\Student;
use App\Models\Course;
$s = new Student("Chanda"); // the librarian fetches src/Models/Student.php automatically
$c = new Course("COMP101"); // ...and src/Models/Course.php
One require, forever. Every class loads itself the first moment it's needed. This
is how every framework works under the hood.
Composer β the professional autoloader
In the real world nobody writes their own autoloader anymore β they let
Composer (PHP's package manager) generate a perfect one. A tiny
composer.json file declares the mapping:
composer.json{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Run composer dump-autoload in a terminal, then in your code:
require "vendor/autoload.php"; // Composer's generated librarian
Composer also installs libraries (like Laravel components, PDF generators, mailers) with a
single command such as composer require phpmailer/phpmailer β and its autoloader
handles their classes too. For this course our hand-written autoloader is enough, but know that
Composer is where you're heading.
In htdocs/learn, create the folder structure src/Models. Put a
namespaced class App\Models\Course (with a $code property) in
src/Models/Course.php. Create the autoload.php from above and an
index.php that creates a Course and echoes its code β with no direct
require of the class file.
Show solution
src/Models/Course.php<?php
namespace App\Models;
class Course {
public function __construct(public string $code) {}
}
index.php<?php
require "autoload.php";
use App\Models\Course;
$c = new Course("COMP101");
echo "Loaded course: $c->code";
What problem do namespaces mainly solve?
Which function registers an autoloader in plain PHP?
- A namespace is a class's full address:
namespace App\Models;β classApp\Models\Student. use App\Models\Student;imports it;use ... as Alias;renames on import.- PSR-4 convention: namespace mirrors folder path, one class per file, file named after the class.
- Autoloading (
spl_autoload_register) loads class files automatically on first use β one require to rule them all. - Composer is the professional tool: it installs libraries and generates the autoloader (
vendor/autoload.php).