<?php OOP: Zero to Hero Chapter 11 of 20

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.

🏘️
Real-world analogy

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");
Convention that everyone follows

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

πŸ“š
Real-world analogy

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.

✏️ Try it yourself

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";
Loaded course: COMP101
Quick quiz

What problem do namespaces mainly solve?

Quick quiz

Which function registers an autoloader in plain PHP?

πŸ”‘ Key points
  • A namespace is a class's full address: namespace App\Models; β†’ class App\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).