Lab 13: Namespaces & Autoloading

Objective

Organize PHP code with namespaces, implement PSR-4 autoloading, use Composer for dependency management, and understand how modern PHP projects are structured.

Background

Before namespaces (PHP 5.3), class names had to be globally unique — leading to names like Zend_Db_Adapter_Pdo_Mysql. Namespaces let you use short names like DB\Adapter\Pdo\Mysql and organize code hierarchically. Composer's PSR-4 autoloading maps namespace prefixes to directory paths, eliminating manual require statements. Every modern PHP project uses this.

Time

30 minutes

Prerequisites

  • Lab 07 (OOP)

Tools

  • PHP 8.3 CLI

  • Docker image: zchencow/innozverse-php:latest


Lab Instructions

Step 1: Namespace Basics

💡 Fully-qualified class names start with \: \App\User means "root namespace → App → User". A use statement creates an alias in the current file scope: use App\User; lets you write new User(). Without use, you need the full path every time.

📸 Verified Output:


Step 2: use Aliases & Conflict Resolution

💡 use aliases (as) resolve naming conflicts — if two packages both have a Collection class, use use Vendor1\Collection as V1Collection. Group use (PHP 7.0+) is purely syntactic sugar: use App\{User, Product} is identical to two separate use statements.

📸 Verified Output:


Step 3: PSR-4 Directory Structure

💡 PSR-4 rule: namespace App\Models\Product maps to file src/Models/Product.php when configured as "App\\" => "src/". The backslash in the namespace becomes a directory separator. This is the universal standard — Composer, Laravel, Symfony, and every modern PHP library follows PSR-4.

📸 Verified Output:


Step 4: Manual Autoloader

💡 spl_autoload_register registers a function PHP calls when it encounters an unknown class name. Composer generates a highly-optimized version of this at vendor/autoload.php. The class map (static lookup table) Composer builds from composer dump-autoload --optimize is 10× faster than path-based lookup.

📸 Verified Output:


Step 5: Composer Basics

💡 Commit composer.lock to version control — it locks every dependency to an exact version, ensuring everyone on the team (and your CI/CD) installs identical packages. composer.json specifies constraints (^8.3 = >=8.3, <9.0); composer.lock specifies exact versions.

📸 Verified Output:


Step 6: Interfaces in Namespaces

📸 Verified Output:


Step 7: Constants & Functions in Namespaces

💡 Namespace constants and functions are organized just like classes. use const App\Math\PI imports a constant; use function App\Math\circleArea imports a function. Without the use, you'd write \App\Math\circleArea(5). Built-in PHP functions are always in the root namespace.

📸 Verified Output:


Step 8: Complete — Service Container (Dependency Injection)

💡 The Service Container (IoC Container) is the heart of Laravel — it knows how to build any class and inject its dependencies automatically. Our mini-container does the same: bind registers a factory; singleton ensures only one instance; make builds and returns the object, resolving its dependencies recursively.

📸 Verified Output:


Summary

Namespaces and autoloading transform PHP from a collection of files into a structured project. You've used namespace declarations, use aliases, PSR-4 directory structure, a manual autoloader, Composer basics, namespaced constants/functions, and built a service container. This is exactly how Laravel, Symfony, and every modern PHP framework is organized.

Further Reading

Last updated